From 3bd31c35895f3e39b0abdf78aeba7efa69805b16 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 18 Jun 2013 10:51:28 +0000 Subject: [PATCH] Proyecto utilizando Yiinitializr. git-svn-id: https://192.168.0.254/svn/Rodax.factuges_web/branches/yiinitializr@6 e455b18d-f7fe-5245-9c43-e2c35af70a32 --- src/.gitignore | 44 + src/README.md | 134 + src/backend/.htaccess | 1 + src/backend/components/.gitkeep | 0 src/backend/config/backend.php | 66 + src/backend/config/env.php | 33 + src/backend/config/env/dev.php | 33 + src/backend/config/env/prod.php | 27 + src/backend/controllers/SiteController.php | 32 + src/backend/extensions/.gitkeep | 0 src/backend/helpers/.gitkeep | 0 src/backend/lib/.gitkeep | 0 src/backend/models/.gitkeep | 0 src/backend/modules/.gitkeep | 0 src/backend/tests/.gitkeep | 0 src/backend/views/layouts/main.php | 106 + src/backend/views/site/error.php | 1 + src/backend/views/site/index.php | 50 + src/backend/widgets/.gitkeep | 0 src/backend/www/.htaccess | 550 + .../apple-touch-icon-114x114-precomposed.png | Bin 0 -> 1032 bytes .../apple-touch-icon-57x57-precomposed.png | Bin 0 -> 640 bytes .../apple-touch-icon-72x72-precomposed.png | Bin 0 -> 747 bytes .../www/apple-touch-icon-precomposed.png | Bin 0 -> 640 bytes src/backend/www/apple-touch-icon.png | Bin 0 -> 640 bytes src/backend/www/css/bootstrap-responsive.css | 1109 + .../www/css/bootstrap-responsive.min.css | 9 + src/backend/www/css/bootstrap.css | 6158 ++++++ src/backend/www/css/bootstrap.min.css | 9 + .../www/css/fonts/Chunkfive-webfont.eot | Bin 0 -> 18610 bytes .../www/css/fonts/Chunkfive-webfont.svg | 121 + .../www/css/fonts/Chunkfive-webfont.ttf | Bin 0 -> 18412 bytes .../www/css/fonts/Chunkfive-webfont.woff | Bin 0 -> 12136 bytes .../www/css/fonts/League_Gothic-webfont.eot | Bin 0 -> 25486 bytes .../www/css/fonts/League_Gothic-webfont.svg | 148 + .../www/css/fonts/League_Gothic-webfont.ttf | Bin 0 -> 25272 bytes .../www/css/fonts/League_Gothic-webfont.woff | Bin 0 -> 15736 bytes src/backend/www/css/main.css | 22 + src/backend/www/css/style.css | 767 + src/backend/www/favicon.ico | Bin 0 -> 1150 bytes src/backend/www/humans.txt | 20 + src/backend/www/img/github-logo.png | Bin 0 -> 22194 bytes src/backend/www/img/html5-logo-165-cut.png | Bin 0 -> 6472 bytes src/backend/www/index.php | 21 + src/backend/www/js/libs/bootstrap.js | 2268 ++ src/backend/www/js/libs/bootstrap.min.js | 6 + src/backend/www/js/libs/jquery-1.9.1.js | 9597 +++++++++ src/backend/www/js/libs/jquery-1.9.1.min.js | 5 + .../www/js/libs/modernizr-2.0.6.min.js | 4 + .../libs/modernizr-2.6.2-respond-1.1.0.min.js | 11 + src/backend/www/js/main.js | 1 + src/backend/www/js/plugins.js | 24 + src/backend/www/js/script.js | 222 + src/backend/www/robots.txt | 3 + src/common/.htaccess | 1 + src/common/components/.gitkeep | 0 src/common/config/env.php | 33 + src/common/config/env/dev.php | 33 + src/common/config/env/prod.php | 27 + src/common/config/main.php | 58 + src/common/config/test.php | 16 + src/common/data/.gitkeep | 0 src/common/data/testdrive.db | Bin 0 -> 5120 bytes src/common/extensions/.gitkeep | 0 .../extensions/components/EActiveRecord.php | 119 + .../extensions/components/EController.php | 106 + .../extensions/components/EWebApplication.php | 43 + src/common/helpers/.gitkeep | 0 src/common/lib/Yiinitializr/CHANGELOG | 6 + src/common/lib/Yiinitializr/Cli/Console.php | 487 + src/common/lib/Yiinitializr/Cli/Daemon.php | 163 + .../lib/Yiinitializr/Composer/Callback.php | 202 + .../lib/Yiinitializr/Helpers/ArrayX.php | 416 + .../lib/Yiinitializr/Helpers/Config.php | 94 + .../lib/Yiinitializr/Helpers/Initializer.php | 249 + src/common/lib/Yiinitializr/LICENSE | 31 + src/common/lib/Yiinitializr/README.md | 128 + src/common/lib/Yiinitializr/composer.json | 30 + .../lib/Yiinitializr/config/console.php | 33 + src/common/lib/Yiinitializr/config/env.lock | 1 + .../lib/Yiinitializr/config/settings.php | 52 + .../lib/vendor/2amigos/yiistrap/.gitignore | 29 + .../lib/vendor/2amigos/yiistrap/README.md | 4 + .../lib/vendor/2amigos/yiistrap/TODO.md | 22 + .../assets/css/bootstrap-responsive.css | 1109 + .../assets/css/bootstrap-responsive.min.css | 9 + .../2amigos/yiistrap/assets/css/bootstrap.css | 6158 ++++++ .../yiistrap/assets/css/bootstrap.min.css | 9 + .../assets/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../assets/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes .../2amigos/yiistrap/assets/js/bootstrap.js | 2268 ++ .../yiistrap/assets/js/bootstrap.min.js | 6 + .../2amigos/yiistrap/behaviors/TbWidget.php | 78 + .../2amigos/yiistrap/components/TbApi.php | 209 + .../lib/vendor/2amigos/yiistrap/composer.json | 19 + .../2amigos/yiistrap/helpers/TbHtml.php | 4065 ++++ .../2amigos/yiistrap/widgets/TbActiveForm.php | 693 + .../2amigos/yiistrap/widgets/TbAffix.php | 61 + .../2amigos/yiistrap/widgets/TbAlert.php | 94 + .../2amigos/yiistrap/widgets/TbBreadcrumb.php | 79 + .../yiistrap/widgets/TbButtonColumn.php | 84 + .../2amigos/yiistrap/widgets/TbCollapse.php | 77 + .../2amigos/yiistrap/widgets/TbDataColumn.php | 93 + .../2amigos/yiistrap/widgets/TbGridView.php | 96 + .../2amigos/yiistrap/widgets/TbHeroUnit.php | 57 + .../2amigos/yiistrap/widgets/TbListView.php | 35 + .../2amigos/yiistrap/widgets/TbModal.php | 263 + .../vendor/2amigos/yiistrap/widgets/TbNav.php | 174 + .../2amigos/yiistrap/widgets/TbNavbar.php | 128 + .../2amigos/yiistrap/widgets/TbPager.php | 141 + .../2amigos/yiistrap/widgets/TbScrollspy.php | 56 + .../2amigos/yiistrap/widgets/TbTabs.php | 255 + .../2amigos/yiistrap/widgets/TbThumbnails.php | 61 + .../2amigos/yiistrap/widgets/TbTypeAhead.php | 136 + .../lib/vendor/2amigos/yiiwheels/.gitignore | 27 + .../lib/vendor/2amigos/yiiwheels/README.md | 12 + .../vendor/2amigos/yiiwheels/YiiWheels.php | 122 + .../vendor/2amigos/yiiwheels/assets/README.md | 5 + .../assets/css/bootstrap-image-gallery.css | 146 + .../css/bootstrap-image-gallery.min.css | 21 + .../yiiwheels/assets/css/bootstrap-notify.css | 6 + .../2amigos/yiiwheels/assets/img/loading.gif | Bin 0 -> 1877 bytes .../assets/js/bootstrap-bootbox.min.js | 35 + .../assets/js/bootstrap-image-gallery.js | 395 + .../assets/js/bootstrap-image-gallery.min.js | 1 + .../yiiwheels/assets/js/bootstrap-notify.js | 92 + .../yiiwheels/assets/js/declarative.min.js | 16 + .../assets/js/jquery.mousewheel.min.js | 12 + .../2amigos/yiiwheels/assets/js/json2.min.js | 7 + .../2amigos/yiiwheels/assets/js/moment.min.js | 6 + .../2amigos/yiiwheels/assets/js/require.js | 2037 ++ .../2amigos/yiiwheels/assets/js/spin.js | 369 + .../yiiwheels/assets/js/underscore.min.js | 1 + .../2amigos/yiiwheels/behaviors/WhPlugin.php | 59 + .../vendor/2amigos/yiiwheels/composer.json | 23 + .../2amigos/yiiwheels/helpers/WhHtml.php | 327 + .../yiiwheels/widgets/ace/WhAceEditor.php | 135 + .../yiiwheels/widgets/ace/assets/js/ace.js | 5608 +++++ .../widgets/ace/assets/js/ext-searchbox.js | 86 + .../widgets/ace/assets/js/ext-spellcheck.js | 19 + .../ace/assets/js/ext-static_highlight.js | 14 + .../widgets/ace/assets/js/ext-textarea.js | 185 + .../widgets/ace/assets/js/keybinding-emacs.js | 113 + .../widgets/ace/assets/js/keybinding-vim.js | 592 + .../widgets/ace/assets/js/mode-abap.js | 78 + .../widgets/ace/assets/js/mode-asciidoc.js | 202 + .../widgets/ace/assets/js/mode-c9search.js | 60 + .../widgets/ace/assets/js/mode-c_cpp.js | 248 + .../widgets/ace/assets/js/mode-clojure.js | 78 + .../widgets/ace/assets/js/mode-coffee.js | 140 + .../widgets/ace/assets/js/mode-coldfusion.js | 584 + .../widgets/ace/assets/js/mode-csharp.js | 217 + .../widgets/ace/assets/js/mode-css.js | 250 + .../widgets/ace/assets/js/mode-curly.js | 627 + .../widgets/ace/assets/js/mode-dart.js | 71 + .../widgets/ace/assets/js/mode-diff.js | 42 + .../widgets/ace/assets/js/mode-django.js | 638 + .../widgets/ace/assets/js/mode-dot.js | 115 + .../widgets/ace/assets/js/mode-glsl.js | 261 + .../widgets/ace/assets/js/mode-golang.js | 236 + .../widgets/ace/assets/js/mode-groovy.js | 328 + .../widgets/ace/assets/js/mode-haml.js | 111 + .../widgets/ace/assets/js/mode-haxe.js | 215 + .../widgets/ace/assets/js/mode-html.js | 610 + .../widgets/ace/assets/js/mode-jade.js | 495 + .../widgets/ace/assets/js/mode-java.js | 316 + .../widgets/ace/assets/js/mode-javascript.js | 283 + .../widgets/ace/assets/js/mode-json.js | 204 + .../widgets/ace/assets/js/mode-jsp.js | 378 + .../widgets/ace/assets/js/mode-jsx.js | 220 + .../widgets/ace/assets/js/mode-latex.js | 78 + .../widgets/ace/assets/js/mode-less.js | 236 + .../widgets/ace/assets/js/mode-liquid.js | 245 + .../widgets/ace/assets/js/mode-lisp.js | 28 + .../widgets/ace/assets/js/mode-livescript.js | 113 + .../widgets/ace/assets/js/mode-lua.js | 114 + .../widgets/ace/assets/js/mode-luapage.js | 739 + .../widgets/ace/assets/js/mode-lucene.js | 22 + .../widgets/ace/assets/js/mode-makefile.js | 76 + .../widgets/ace/assets/js/mode-markdown.js | 765 + .../widgets/ace/assets/js/mode-objectivec.js | 160 + .../widgets/ace/assets/js/mode-ocaml.js | 69 + .../widgets/ace/assets/js/mode-pascal.js | 232 + .../widgets/ace/assets/js/mode-perl.js | 95 + .../widgets/ace/assets/js/mode-pgsql.js | 144 + .../widgets/ace/assets/js/mode-php.js | 437 + .../widgets/ace/assets/js/mode-powershell.js | 206 + .../widgets/ace/assets/js/mode-python.js | 80 + .../yiiwheels/widgets/ace/assets/js/mode-r.js | 113 + .../widgets/ace/assets/js/mode-rdoc.js | 62 + .../widgets/ace/assets/js/mode-rhtml.js | 686 + .../widgets/ace/assets/js/mode-ruby.js | 128 + .../widgets/ace/assets/js/mode-sass.js | 466 + .../widgets/ace/assets/js/mode-scad.js | 239 + .../widgets/ace/assets/js/mode-scala.js | 325 + .../widgets/ace/assets/js/mode-scheme.js | 28 + .../widgets/ace/assets/js/mode-scss.js | 242 + .../widgets/ace/assets/js/mode-sh.js | 61 + .../widgets/ace/assets/js/mode-sql.js | 37 + .../widgets/ace/assets/js/mode-stylus.js | 121 + .../widgets/ace/assets/js/mode-svg.js | 496 + .../widgets/ace/assets/js/mode-tcl.js | 112 + .../widgets/ace/assets/js/mode-tex.js | 53 + .../widgets/ace/assets/js/mode-text.js | 0 .../widgets/ace/assets/js/mode-textile.js | 50 + .../widgets/ace/assets/js/mode-tm_snippet.js | 45 + .../widgets/ace/assets/js/mode-tmsnippet.js | 84 + .../widgets/ace/assets/js/mode-typescript.js | 308 + .../widgets/ace/assets/js/mode-vbscript.js | 51 + .../widgets/ace/assets/js/mode-xml.js | 298 + .../widgets/ace/assets/js/mode-xquery.js | 252 + .../widgets/ace/assets/js/mode-yaml.js | 94 + .../widgets/ace/assets/js/theme-ambiance.js | 5 + .../widgets/ace/assets/js/theme-chaos.js | 5 + .../widgets/ace/assets/js/theme-chrome.js | 5 + .../widgets/ace/assets/js/theme-clouds.js | 5 + .../ace/assets/js/theme-clouds_midnight.js | 5 + .../widgets/ace/assets/js/theme-cobalt.js | 5 + .../ace/assets/js/theme-crimson_editor.js | 5 + .../widgets/ace/assets/js/theme-dawn.js | 5 + .../ace/assets/js/theme-dreamweaver.js | 5 + .../widgets/ace/assets/js/theme-eclipse.js | 5 + .../widgets/ace/assets/js/theme-github.js | 5 + .../ace/assets/js/theme-idle_fingers.js | 5 + .../widgets/ace/assets/js/theme-kr.js | 5 + .../widgets/ace/assets/js/theme-merbivore.js | 5 + .../ace/assets/js/theme-merbivore_soft.js | 5 + .../ace/assets/js/theme-mono_industrial.js | 5 + .../widgets/ace/assets/js/theme-monokai.js | 5 + .../ace/assets/js/theme-pastel_on_dark.js | 5 + .../ace/assets/js/theme-solarized_dark.js | 5 + .../ace/assets/js/theme-solarized_light.js | 5 + .../widgets/ace/assets/js/theme-textmate.js | 5 + .../widgets/ace/assets/js/theme-tomorrow.js | 5 + .../ace/assets/js/theme-tomorrow_night.js | 5 + .../assets/js/theme-tomorrow_night_blue.js | 5 + .../assets/js/theme-tomorrow_night_bright.js | 5 + .../js/theme-tomorrow_night_eighties.js | 5 + .../widgets/ace/assets/js/theme-twilight.js | 5 + .../ace/assets/js/theme-vibrant_ink.js | 5 + .../widgets/ace/assets/js/theme-xcode.js | 5 + .../widgets/ace/assets/js/worker-coffee.js | 3240 +++ .../widgets/ace/assets/js/worker-css.js | 2315 ++ .../ace/assets/js/worker-javascript.js | 2106 ++ .../widgets/ace/assets/js/worker-json.js | 875 + .../widgets/ace/assets/js/worker-php.js | 2003 ++ .../widgets/ace/assets/js/worker-xquery.js | 11844 +++++++++++ .../widgets/datepicker/WhDatePicker.php | 103 + .../datepicker/assets/build/build.less | 66 + .../assets/build/build_standalone.less | 74 + .../datepicker/assets/css/datepicker.css | 336 + .../assets/js/bootstrap-datepicker.js | 1029 + .../js/locales/bootstrap-datepicker.bg.js | 15 + .../js/locales/bootstrap-datepicker.ca.js | 15 + .../js/locales/bootstrap-datepicker.cs.js | 16 + .../js/locales/bootstrap-datepicker.da.js | 15 + .../js/locales/bootstrap-datepicker.de.js | 17 + .../js/locales/bootstrap-datepicker.el.js | 14 + .../js/locales/bootstrap-datepicker.es.js | 15 + .../js/locales/bootstrap-datepicker.fi.js | 15 + .../js/locales/bootstrap-datepicker.fr.js | 17 + .../js/locales/bootstrap-datepicker.he.js | 16 + .../js/locales/bootstrap-datepicker.hr.js | 14 + .../js/locales/bootstrap-datepicker.hu.js | 17 + .../js/locales/bootstrap-datepicker.id.js | 14 + .../js/locales/bootstrap-datepicker.is.js | 15 + .../js/locales/bootstrap-datepicker.it.js | 17 + .../js/locales/bootstrap-datepicker.ja.js | 14 + .../js/locales/bootstrap-datepicker.kr.js | 14 + .../js/locales/bootstrap-datepicker.lt.js | 17 + .../js/locales/bootstrap-datepicker.lv.js | 17 + .../js/locales/bootstrap-datepicker.ms.js | 15 + .../js/locales/bootstrap-datepicker.nb.js | 15 + .../js/locales/bootstrap-datepicker.nl.js | 15 + .../js/locales/bootstrap-datepicker.pl.js | 16 + .../js/locales/bootstrap-datepicker.pt-BR.js | 15 + .../js/locales/bootstrap-datepicker.pt.js | 15 + .../js/locales/bootstrap-datepicker.ro.js | 16 + .../locales/bootstrap-datepicker.rs-latin.js | 15 + .../js/locales/bootstrap-datepicker.rs.js | 15 + .../js/locales/bootstrap-datepicker.ru.js | 15 + .../js/locales/bootstrap-datepicker.sk.js | 16 + .../js/locales/bootstrap-datepicker.sl.js | 15 + .../js/locales/bootstrap-datepicker.sv.js | 15 + .../js/locales/bootstrap-datepicker.sw.js | 16 + .../js/locales/bootstrap-datepicker.th.js | 15 + .../js/locales/bootstrap-datepicker.tr.js | 16 + .../js/locales/bootstrap-datepicker.uk.js | 15 + .../js/locales/bootstrap-datepicker.zh-CN.js | 15 + .../js/locales/bootstrap-datepicker.zh-TW.js | 14 + .../datepicker/assets/less/datepicker.less | 180 + .../daterangepicker/WhDateRangePicker.php | 147 + .../assets/css/daterangepicker.css | 213 + .../assets/js/daterangepicker.js | 766 + .../yiiwheels/widgets/detail/WhDetailView.php | 60 + .../widgets/fileupload/WhBasicFileUpload.php | 87 + .../widgets/fileupload/WhFileUpload.php | 173 + .../assets/css/jquery.fileupload-ui.css | 94 + .../widgets/fileupload/assets/img/loading.gif | Bin 0 -> 1877 bytes .../fileupload/assets/img/progressbar.gif | Bin 0 -> 3323 bytes .../assets/js/canvas-to-blob.min.js | 28 + .../js/cors/jquery.postmessage-transport.js | 117 + .../assets/js/cors/jquery.xdr-transport.js | 86 + .../assets/js/jquery.fileupload-fp.js | 222 + .../assets/js/jquery.fileupload-ip.js | 160 + .../assets/js/jquery.fileupload-locale.js | 29 + .../assets/js/jquery.fileupload-ui.js | 731 + .../fileupload/assets/js/jquery.fileupload.js | 1109 + .../assets/js/jquery.iframe-transport.js | 172 + .../fileupload/assets/js/load-image.min.js | 47 + .../widgets/fileupload/assets/js/main.js | 85 + .../widgets/fileupload/assets/js/tmpl.min.js | 23 + .../js/vendor/jquery-ui-1.9.1.custom.min.js | 3945 ++++ .../assets/js/vendor/jquery.ui.widget.js | 531 + .../widgets/fileupload/views/download.php | 34 + .../widgets/fileupload/views/form.php | 45 + .../widgets/fileupload/views/upload.php | 37 + .../widgets/fineuploader/WhFineUploader.php | 175 + .../fineuploader/assets/css/fineuploader.css | 174 + .../fineuploader/assets/img/loading.gif | Bin 0 -> 1688 bytes .../fineuploader/assets/img/processing.gif | Bin 0 -> 3209 bytes .../assets/js/jquery.fineuploader-3.2.js | 3245 +++ .../assets/js/jquery.fineuploader-3.2.min.js | 1994 ++ .../yiiwheels/widgets/form/WhActiveForm.php | 167 + .../widgets/google/WhVisualizationChart.php | 90 + .../widgets/grid/WhRelationalColumn.php | 211 + .../widgets/highcharts/WhHighCharts.php | 112 + .../assets/js/adapters/mootools-adapter.js | 92 + .../js/adapters/mootools-adapter.src.js | 326 + .../assets/js/adapters/prototype-adapter.js | 101 + .../js/adapters/prototype-adapter.src.js | 382 + .../highcharts/assets/js/highcharts-more.js | 198 + .../highcharts/assets/js/highcharts.js | 3273 +++ .../highcharts/assets/js/highcharts.src.js | 14703 +++++++++++++ .../assets/js/modules/canvas-tools.js | 1590 ++ .../assets/js/modules/canvas-tools.src.js | 3187 +++ .../highcharts/assets/js/modules/exporting.js | 159 + .../assets/js/modules/exporting.src.js | 739 + .../highcharts/assets/js/themes/dark-blue.js | 263 + .../highcharts/assets/js/themes/dark-green.js | 263 + .../highcharts/assets/js/themes/gray.js | 262 + .../highcharts/assets/js/themes/grid.js | 95 + .../highcharts/assets/js/themes/skies.js | 89 + .../widgets/html5editor/WhHtml5Editor.php | 117 + .../assets/css/bootstrap-wysihtml5.css | 102 + .../html5editor/assets/css/wysiwyg-color.css | 71 + .../assets/js/bootstrap-wysihtml5.js | 458 + .../js/locale/bootstrap-wysihtml5.bg-BG.js | 48 + .../js/locale/bootstrap-wysihtml5.de-DE.js | 48 + .../js/locale/bootstrap-wysihtml5.es-ES.js | 34 + .../js/locale/bootstrap-wysihtml5.fr-FR.js | 49 + .../js/locale/bootstrap-wysihtml5.fr-NL.js | 48 + .../js/locale/bootstrap-wysihtml5.hu-HU.js | 48 + .../js/locale/bootstrap-wysihtml5.pt-BR.js | 48 + .../js/locale/bootstrap-wysihtml5.sv-SE.js | 48 + .../html5editor/assets/js/wysihtml5-0.3.0.js | 9523 +++++++++ .../widgets/maskmoney/WhMaskMoney.php | 77 + .../maskmoney/assets/js/jquery.maskmoney.js | 359 + .../yiiwheels/widgets/modal/WhModal.php | 57 + .../modal/assets/css/bootstrap-modal.css | 236 + .../widgets/modal/assets/img/ajax-loader.gif | Bin 0 -> 1737 bytes .../modal/assets/js/bootstrap-modal.js | 377 + .../modal/assets/js/bootstrap-modalmanager.js | 419 + .../widgets/multiselect/WhMultiSelect.php | 93 + .../assets/css/bootstrap-multiselect.css | 0 .../assets/js/bootstrap-multiselect.js | 217 + .../widgets/rangeslider/WhRangeSlider.php | 387 + .../rangeslider/assets/css/classic.css | 95 + .../widgets/rangeslider/assets/css/iThing.css | 193 + .../assets/css/icons-classic/label.png | Bin 0 -> 9343 bytes .../css/icons-classic/resultset_next.png | Bin 0 -> 3022 bytes .../css/icons-classic/resultset_previous.png | Bin 0 -> 3023 bytes .../assets/js/jQAllRangeSliders-min.js | 2 + .../js/jQAllRangeSliders-withRuler-min.js | 2 + .../yiiwheels/widgets/redactor/WhRedactor.php | 131 + .../widgets/redactor/assets/css/redactor.css | 830 + .../widgets/redactor/assets/js/langs/ar.js | 69 + .../widgets/redactor/assets/js/langs/az.js | 68 + .../widgets/redactor/assets/js/langs/ba.js | 72 + .../widgets/redactor/assets/js/langs/bg.js | 70 + .../widgets/redactor/assets/js/langs/by.js | 68 + .../widgets/redactor/assets/js/langs/ca.js | 68 + .../widgets/redactor/assets/js/langs/cs.js | 80 + .../widgets/redactor/assets/js/langs/da.js | 69 + .../widgets/redactor/assets/js/langs/de.js | 73 + .../widgets/redactor/assets/js/langs/el.js | 68 + .../widgets/redactor/assets/js/langs/eo.js | 69 + .../widgets/redactor/assets/js/langs/es.js | 69 + .../widgets/redactor/assets/js/langs/es_ar.js | 69 + .../widgets/redactor/assets/js/langs/fa.js | 69 + .../widgets/redactor/assets/js/langs/fi.js | 72 + .../widgets/redactor/assets/js/langs/fr.js | 68 + .../widgets/redactor/assets/js/langs/he.js | 68 + .../widgets/redactor/assets/js/langs/hr.js | 72 + .../widgets/redactor/assets/js/langs/hu.js | 70 + .../widgets/redactor/assets/js/langs/id.js | 69 + .../widgets/redactor/assets/js/langs/it.js | 71 + .../widgets/redactor/assets/js/langs/ja.js | 69 + .../widgets/redactor/assets/js/langs/ko.js | 69 + .../widgets/redactor/assets/js/langs/lt.js | 68 + .../widgets/redactor/assets/js/langs/lv.js | 68 + .../widgets/redactor/assets/js/langs/mk.js | 68 + .../widgets/redactor/assets/js/langs/nl.js | 72 + .../widgets/redactor/assets/js/langs/no_NB.js | 68 + .../widgets/redactor/assets/js/langs/pl.js | 69 + .../widgets/redactor/assets/js/langs/pt_br.js | 75 + .../widgets/redactor/assets/js/langs/ro.js | 69 + .../widgets/redactor/assets/js/langs/ru.js | 69 + .../widgets/redactor/assets/js/langs/sk.js | 69 + .../widgets/redactor/assets/js/langs/sl.js | 72 + .../widgets/redactor/assets/js/langs/sq.js | 72 + .../redactor/assets/js/langs/sr-cir.js | 72 + .../redactor/assets/js/langs/sr-lat.js | 72 + .../widgets/redactor/assets/js/langs/sv.js | 69 + .../widgets/redactor/assets/js/langs/tr.js | 69 + .../widgets/redactor/assets/js/langs/ua.js | 70 + .../widgets/redactor/assets/js/langs/vi.js | 68 + .../widgets/redactor/assets/js/langs/zh_cn.js | 70 + .../widgets/redactor/assets/js/langs/zh_tw.js | 67 + .../assets/js/plugins/clips/clips.css | 37 + .../redactor/assets/js/plugins/clips/clips.js | 36 + .../js/plugins/fullscreen/fullscreen.js | 72 + .../widgets/redactor/assets/js/redactor.js | 3641 ++++ .../redactor/assets/js/redactor.min.js | 35 + .../yiiwheels/widgets/redactor/license.md | 15 + .../yiiwheels/widgets/select2/WhSelect2.php | 114 + .../widgets/select2/assets/css/select2.css | 636 + .../select2/assets/img/select2-spinner.gif | Bin 0 -> 1849 bytes .../widgets/select2/assets/img/select2.png | Bin 0 -> 613 bytes .../widgets/select2/assets/img/select2x2.png | Bin 0 -> 845 bytes .../assets/js/locale/select2_locale_it.js | 29 + .../widgets/select2/assets/js/select2.js | 2813 +++ .../widgets/sparklines/WhSparklines.php | 93 + .../sparklines/assets/js/jquery.sparkline.js | 3066 +++ .../assets/js/jquery.sparkline.min.js | 654 + .../yiiwheels/widgets/timeago/WhTimeAgo.php | 96 + .../timeago/assets/js/jquery.timeago.js | 166 + .../timeago/assets/js/locales/README.md | 27 + .../assets/js/locales/jquery.timeago.ar.js | 45 + .../assets/js/locales/jquery.timeago.bg.js | 18 + .../assets/js/locales/jquery.timeago.bs.js | 49 + .../assets/js/locales/jquery.timeago.ca.js | 18 + .../assets/js/locales/jquery.timeago.cy.js | 20 + .../assets/js/locales/jquery.timeago.cz.js | 18 + .../assets/js/locales/jquery.timeago.da.js | 18 + .../assets/js/locales/jquery.timeago.de.js | 18 + .../assets/js/locales/jquery.timeago.el.js | 18 + .../js/locales/jquery.timeago.en-short.js | 20 + .../assets/js/locales/jquery.timeago.en.js | 20 + .../assets/js/locales/jquery.timeago.es.js | 18 + .../assets/js/locales/jquery.timeago.fa.js | 21 + .../assets/js/locales/jquery.timeago.fi.js | 28 + .../js/locales/jquery.timeago.fr-short.js | 16 + .../assets/js/locales/jquery.timeago.fr.js | 17 + .../assets/js/locales/jquery.timeago.he.js | 18 + .../assets/js/locales/jquery.timeago.hr.js | 49 + .../assets/js/locales/jquery.timeago.hu.js | 18 + .../assets/js/locales/jquery.timeago.hy.js | 18 + .../assets/js/locales/jquery.timeago.id.js | 18 + .../assets/js/locales/jquery.timeago.it.js | 16 + .../assets/js/locales/jquery.timeago.ja.js | 19 + .../assets/js/locales/jquery.timeago.ko.js | 17 + .../assets/js/locales/jquery.timeago.mk.js | 20 + .../assets/js/locales/jquery.timeago.nl.js | 20 + .../assets/js/locales/jquery.timeago.no.js | 18 + .../assets/js/locales/jquery.timeago.pl.js | 39 + .../assets/js/locales/jquery.timeago.pt-br.js | 16 + .../assets/js/locales/jquery.timeago.pt.js | 16 + .../assets/js/locales/jquery.timeago.ro.js | 18 + .../assets/js/locales/jquery.timeago.ru.js | 44 + .../assets/js/locales/jquery.timeago.sk.js | 18 + .../assets/js/locales/jquery.timeago.sv.js | 18 + .../assets/js/locales/jquery.timeago.th.js | 20 + .../assets/js/locales/jquery.timeago.tr.js | 16 + .../assets/js/locales/jquery.timeago.uk.js | 44 + .../assets/js/locales/jquery.timeago.uz.js | 29 + .../assets/js/locales/jquery.timeago.zh-CN.js | 20 + .../assets/js/locales/jquery.timeago.zh-TW.js | 20 + .../widgets/timepicker/WhTimePicker.php | 110 + .../assets/css/bootstrap-timepicker.css | 143 + .../assets/css/bootstrap-timepicker.min.css | 142 + .../assets/js/bootstrap-timepicker.js | 878 + .../assets/js/bootstrap-timepicker.min.js | 276 + .../timepicker/assets/less/timepicker.less | 146 + .../widgets/toggle/WhToggleAction.php | 112 + .../widgets/toggle/WhToggleButton.php | 226 + .../widgets/toggle/WhToggleColumn.php | 259 + .../assets/css/bootstrap-toggle-buttons.css | 154 + .../toggle/assets/js/jquery.toggle.buttons.js | 271 + .../widgets/typeahead/WhTypeAhead.php | 92 + .../typeahead/assets/css/typeahead.css | 82 + .../typeahead/assets/css/typeahead.min.css | 71 + .../widgets/typeahead/assets/js/typeahead.js | 981 + .../typeahead/assets/js/typeahead.min.js | 437 + src/common/lib/vendor/autoload.php | 7 + .../lib/vendor/composer/ClassLoader.php | 246 + .../lib/vendor/composer/autoload_classmap.php | 9 + .../vendor/composer/autoload_namespaces.php | 10 + .../lib/vendor/composer/autoload_real.php | 43 + src/common/lib/vendor/composer/installed.json | 103 + src/common/lib/vendor/yiisoft/yii/.gitignore | 65 + src/common/lib/vendor/yiisoft/yii/.mailmap | 17 + src/common/lib/vendor/yiisoft/yii/.travis.yml | 18 + src/common/lib/vendor/yiisoft/yii/CHANGELOG | 1640 ++ .../lib/vendor/yiisoft/yii/CONTRIBUTING.md | 38 + src/common/lib/vendor/yiisoft/yii/LICENSE | 31 + src/common/lib/vendor/yiisoft/yii/README | 64 + src/common/lib/vendor/yiisoft/yii/README.md | 65 + src/common/lib/vendor/yiisoft/yii/UPGRADE | 494 + .../lib/vendor/yiisoft/yii/build/.htaccess | 1 + src/common/lib/vendor/yiisoft/yii/build/build | 17 + .../lib/vendor/yiisoft/yii/build/build.bat | 23 + .../lib/vendor/yiisoft/yii/build/build.xml | 276 + .../yiisoft/yii/build/commands/ApiCommand.php | 364 + .../yii/build/commands/AutoloadCommand.php | 83 + .../yii/build/commands/BlogLatexCommand.php | 79 + .../yii/build/commands/CheckBomCommand.php | 58 + .../yii/build/commands/CldrCommand.php | 509 + .../yii/build/commands/GuideLatexCommand.php | 79 + .../yii/build/commands/LiteCommand.php | 219 + .../build/commands/TranslationsCommand.php | 162 + .../yii/build/commands/Utf8Command.php | 196 + .../yii/build/commands/api/ApiModel.php | 817 + .../yii/build/commands/api/assets/css/api.css | 105 + .../build/commands/api/assets/css/style.css | 32 + .../build/commands/api/assets/js/jquery.js | 3549 ++++ .../yii/build/commands/api/layouts/main.php | 52 + .../build/commands/api/views/chmContents.php | 35 + .../yii/build/commands/api/views/chmIndex.php | 42 + .../build/commands/api/views/chmProject.php | 22 + .../yii/build/commands/api/views/class.php | 29 + .../build/commands/api/views/classSummary.php | 46 + .../build/commands/api/views/eventDetails.php | 23 + .../build/commands/api/views/eventSummary.php | 25 + .../yii/build/commands/api/views/index.php | 23 + .../commands/api/views/methodDetails.php | 46 + .../commands/api/views/methodSummary.php | 28 + .../commands/api/views/propertyDetails.php | 24 + .../commands/api/views/propertySummary.php | 29 + .../yii/build/commands/api/views/seeAlso.php | 9 + .../build/commands/api/views/sourceCode.php | 4 + .../yiisoft/yii/build/commands/blog/blog.tex | 30 + .../yii/build/commands/blog/license.tex | 37 + .../yii/build/commands/blog/preamble.tex | 144 + .../yiisoft/yii/build/commands/blog/title.tex | 25 + .../yii/build/commands/guide/guide.tex | 30 + .../yii/build/commands/guide/license.tex | 37 + .../yii/build/commands/guide/preamble.tex | 144 + .../yii/build/commands/guide/title.tex | 25 + .../yii/build/commands/lite/css/bg.gif | Bin 0 -> 169 bytes .../yii/build/commands/lite/css/form.css | 108 + .../yii/build/commands/lite/css/main.css | 111 + .../yiisoft/yii/build/commands/lite/index.php | 5 + .../build/commands/lite/protected/.htaccess | 1 + .../lite/protected/components/MainMenu.php | 68 + .../protected/components/UserIdentity.php | 27 + .../protected/components/views/mainMenu.php | 6 + .../commands/lite/protected/config/main.php | 21 + .../protected/controllers/PostController.php | 168 + .../protected/controllers/SiteController.php | 57 + .../commands/lite/protected/data/source.db | Bin 0 -> 18432 bytes .../lite/protected/models/LoginForm.php | 59 + .../commands/lite/protected/models/Post.php | 34 + .../lite/protected/views/layouts/main.php | 39 + .../lite/protected/views/post/create.php | 34 + .../lite/protected/views/post/list.php | 27 + .../lite/protected/views/post/show.php | 40 + .../lite/protected/views/post/update.php | 35 + .../lite/protected/views/site/index.php | 41 + .../lite/protected/views/site/login.php | 40 + .../yii/build/commands/markdown/Markdown.php | 11 + .../commands/markdown/MarkdownHtml2Tex.php | 263 + .../commands/markdown/MarkdownParser.php | 88 + .../commands/translations/report_html.php | 46 + .../yii/build/generate_accessors_phpdoc.php | 127 + .../yiisoft/yii/build/tasks/YiiInitTask.php | 80 + .../yiisoft/yii/build/tasks/YiiPearTask.php | 131 + .../lib/vendor/yiisoft/yii/composer.json | 73 + .../yiisoft/yii/demos/blog/assets/.gitignore | 1 + .../vendor/yiisoft/yii/demos/blog/css/bg.gif | Bin 0 -> 243 bytes .../yiisoft/yii/demos/blog/css/form.css | 166 + .../vendor/yiisoft/yii/demos/blog/css/ie.css | 35 + .../yiisoft/yii/demos/blog/css/main.css | 267 + .../yiisoft/yii/demos/blog/css/print.css | 29 + .../yiisoft/yii/demos/blog/css/screen.css | 235 + .../yiisoft/yii/demos/blog/index-test.php | 15 + .../vendor/yiisoft/yii/demos/blog/index.php | 11 + .../yii/demos/blog/protected/.htaccess | 1 + .../blog/protected/components/Controller.php | 23 + .../protected/components/RecentComments.php | 19 + .../blog/protected/components/TagCloud.php | 23 + .../protected/components/UserIdentity.php | 39 + .../blog/protected/components/UserMenu.php | 17 + .../components/views/recentComments.php | 7 + .../protected/components/views/userMenu.php | 6 + .../demos/blog/protected/config/console.php | 8 + .../yii/demos/blog/protected/config/main.php | 76 + .../demos/blog/protected/config/params.php | 19 + .../yii/demos/blog/protected/config/test.php | 25 + .../controllers/CommentController.php | 130 + .../protected/controllers/PostController.php | 216 + .../protected/controllers/SiteController.php | 97 + .../demos/blog/protected/data/blog-test.db | Bin 0 -> 9216 bytes .../yii/demos/blog/protected/data/blog.db | Bin 0 -> 9216 bytes .../yii/demos/blog/protected/data/dbgen.php | 13 + .../blog/protected/data/schema.mysql.sql | 70 + .../blog/protected/data/schema.sqlite.sql | 70 + .../demos/blog/protected/models/Comment.php | 148 + .../blog/protected/models/ContactForm.php | 42 + .../demos/blog/protected/models/LoginForm.php | 74 + .../demos/blog/protected/models/Lookup.php | 76 + .../yii/demos/blog/protected/models/Post.php | 202 + .../yii/demos/blog/protected/models/Tag.php | 159 + .../yii/demos/blog/protected/models/User.php | 124 + .../demos/blog/protected/runtime/.gitignore | 1 + .../blog/protected/tests/WebTestCase.php | 25 + .../demos/blog/protected/tests/bootstrap.php | 10 + .../protected/tests/fixtures/tbl_comment.php | 24 + .../protected/tests/fixtures/tbl_lookup.php | 18 + .../protected/tests/fixtures/tbl_post.php | 13 + .../blog/protected/tests/fixtures/tbl_tag.php | 12 + .../protected/tests/fixtures/tbl_user.php | 9 + .../tests/functional/CommentTest.php | 36 + .../protected/tests/functional/PostTest.php | 30 + .../protected/tests/functional/SiteTest.php | 41 + .../demos/blog/protected/tests/phpunit.xml | 13 + .../yii/demos/blog/protected/tests/readme.txt | 42 + .../blog/protected/tests/unit/CommentTest.php | 57 + .../blog/protected/tests/unit/LookupTest.php | 13 + .../blog/protected/tests/unit/PostTest.php | 18 + .../blog/protected/tests/unit/TagTest.php | 13 + .../blog/protected/tests/unit/UserTest.php | 24 + .../blog/protected/views/comment/_form.php | 40 + .../blog/protected/views/comment/_view.php | 46 + .../blog/protected/views/comment/index.php | 12 + .../blog/protected/views/comment/update.php | 10 + .../blog/protected/views/layouts/column1.php | 7 + .../blog/protected/views/layouts/column2.php | 22 + .../blog/protected/views/layouts/main.php | 55 + .../blog/protected/views/post/_comments.php | 22 + .../demos/blog/protected/views/post/_form.php | 47 + .../demos/blog/protected/views/post/_view.php | 23 + .../demos/blog/protected/views/post/admin.php | 31 + .../blog/protected/views/post/create.php | 8 + .../demos/blog/protected/views/post/index.php | 9 + .../blog/protected/views/post/update.php | 10 + .../demos/blog/protected/views/post/view.php | 36 + .../blog/protected/views/site/contact.php | 70 + .../demos/blog/protected/views/site/error.php | 12 + .../demos/blog/protected/views/site/login.php | 46 + .../blog/protected/views/site/pages/about.php | 9 + .../yiisoft/yii/demos/blog/protected/yiic | 4 + .../yiisoft/yii/demos/blog/protected/yiic.bat | 16 + .../yiisoft/yii/demos/blog/protected/yiic.php | 7 + .../demos/blog/themes/classic/views/.htaccess | 1 + .../yiisoft/yii/demos/hangman/assets/empty | 0 .../yiisoft/yii/demos/hangman/index.php | 7 + .../yii/demos/hangman/protected/.htaccess | 1 + .../demos/hangman/protected/config/main.php | 14 + .../protected/controllers/GameController.php | 222 + .../hangman/protected/controllers/words.txt | 28 + .../yii/demos/hangman/protected/runtime/empty | 0 .../hangman/protected/views/game/guess.php | 21 + .../hangman/protected/views/game/lose.php | 5 + .../hangman/protected/views/game/play.php | 15 + .../hangman/protected/views/game/win.php | 5 + .../hangman/protected/views/layouts/main.php | 14 + .../yiisoft/yii/demos/helloworld/index.php | 7 + .../yii/demos/helloworld/protected/.htaccess | 1 + .../protected/controllers/SiteController.php | 15 + .../phonebook/flex/.actionScriptProperties | 24 + .../yii/demos/phonebook/flex/.flexProperties | 2 + .../yiisoft/yii/demos/phonebook/flex/.project | 18 + .../com.adobe.flexbuilder.project.prefs | 3 + .../org.eclipse.core.resources.prefs | 3 + .../yii/demos/phonebook/flex/bin/AC_OETags.js | 276 + .../phonebook/flex/bin/history/history.css | 6 + .../phonebook/flex/bin/history/history.js | 645 + .../flex/bin/history/historyFrame.html | 29 + .../demos/phonebook/flex/bin/phonebook.html | 121 + .../demos/phonebook/flex/bin/phonebook.swf | Bin 0 -> 637488 bytes .../flex/bin/playerProductInstall.swf | Bin 0 -> 657 bytes .../phonebook/flex/html-template/AC_OETags.js | 276 + .../flex/html-template/history/history.css | 6 + .../flex/html-template/history/history.js | 645 + .../html-template/history/historyFrame.html | 29 + .../flex/html-template/index.template.html | 121 + .../html-template/playerProductInstall.swf | Bin 0 -> 657 bytes .../yii/demos/phonebook/flex/phonebook.mxml | 136 + .../yiisoft/yii/demos/phonebook/index.php | 11 + .../yii/demos/phonebook/protected/.htaccess | 1 + .../protected/components/UserIdentity.php | 27 + .../demos/phonebook/protected/config/main.php | 21 + .../protected/controllers/SiteController.php | 143 + .../phonebook/protected/data/phonebook.db | Bin 0 -> 2048 bytes .../demos/phonebook/protected/data/schema.sql | 6 + .../phonebook/protected/models/Contact.php | 25 + .../phonebook/protected/views/site/index.php | 43 + .../lib/vendor/yiisoft/yii/docs/README.md | 14 + .../yii/docs/blog/ar/start.overview.txt | 14 + .../yiisoft/yii/docs/blog/comment.admin.txt | 88 + .../yiisoft/yii/docs/blog/comment.create.txt | 165 + .../yiisoft/yii/docs/blog/comment.model.txt | 74 + .../yii/docs/blog/es/final.logging.txt | 34 + .../yiisoft/yii/docs/blog/es/final.url.txt | 43 + .../yii/docs/blog/es/portlet.comments.txt | 79 + .../yiisoft/yii/docs/blog/es/portlet.menu.txt | 90 + .../yiisoft/yii/docs/blog/es/portlet.tags.txt | 60 + .../yiisoft/yii/docs/blog/es/post.admin.txt | 108 + .../yiisoft/yii/docs/blog/es/post.create.txt | 95 + .../yiisoft/yii/docs/blog/es/post.display.txt | 106 + .../yiisoft/yii/docs/blog/es/post.model.txt | 209 + .../yii/docs/blog/es/prototype.auth.txt | 105 + .../yii/docs/blog/es/prototype.database.txt | 68 + .../yii/docs/blog/es/prototype.scaffold.txt | 112 + .../yii/docs/blog/es/prototype.summary.txt | 20 + .../yiisoft/yii/docs/blog/es/start.design.txt | 50 + .../yii/docs/blog/es/start.overview.txt | 15 + .../yii/docs/blog/es/start.requirements.txt | 26 + .../yii/docs/blog/es/start.testdrive.txt | 85 + .../vendor/yiisoft/yii/docs/blog/es/toc.txt | 35 + .../yii/docs/blog/final.deployment.txt | 68 + .../yiisoft/yii/docs/blog/final.future.txt | 57 + .../yiisoft/yii/docs/blog/final.logging.txt | 35 + .../yiisoft/yii/docs/blog/final.url.txt | 45 + .../yii/docs/blog/id/comment.admin.txt | 60 + .../yii/docs/blog/id/comment.create.txt | 150 + .../yii/docs/blog/id/comment.model.txt | 74 + .../yii/docs/blog/id/final.deployment.txt | 68 + .../yiisoft/yii/docs/blog/id/final.future.txt | 58 + .../yii/docs/blog/id/final.logging.txt | 35 + .../yiisoft/yii/docs/blog/id/final.url.txt | 45 + .../yii/docs/blog/id/portlet.comments.txt | 82 + .../yiisoft/yii/docs/blog/id/portlet.menu.txt | 94 + .../yiisoft/yii/docs/blog/id/portlet.tags.txt | 62 + .../yiisoft/yii/docs/blog/id/post.admin.txt | 107 + .../yiisoft/yii/docs/blog/id/post.create.txt | 96 + .../yiisoft/yii/docs/blog/id/post.display.txt | 108 + .../yiisoft/yii/docs/blog/id/post.model.txt | 200 + .../yii/docs/blog/id/prototype.auth.txt | 105 + .../yii/docs/blog/id/prototype.database.txt | 70 + .../yii/docs/blog/id/prototype.scaffold.txt | 118 + .../yii/docs/blog/id/prototype.summary.txt | 21 + .../yiisoft/yii/docs/blog/id/start.design.txt | 53 + .../yii/docs/blog/id/start.overview.txt | 10 + .../yii/docs/blog/id/start.requirements.txt | 26 + .../yii/docs/blog/id/start.testdrive.txt | 85 + .../vendor/yiisoft/yii/docs/blog/id/toc.txt | 35 + .../yiisoft/yii/docs/blog/images/schema.png | Bin 0 -> 7036 bytes .../yiisoft/yii/docs/blog/images/schema.vsd | Bin 0 -> 82432 bytes .../yii/docs/blog/ja/comment.admin.txt | 88 + .../yii/docs/blog/ja/comment.create.txt | 164 + .../yii/docs/blog/ja/comment.model.txt | 71 + .../yii/docs/blog/ja/final.deployment.txt | 68 + .../yiisoft/yii/docs/blog/ja/final.future.txt | 58 + .../yii/docs/blog/ja/final.logging.txt | 35 + .../yiisoft/yii/docs/blog/ja/final.url.txt | 47 + .../yii/docs/blog/ja/portlet.comments.txt | 81 + .../yiisoft/yii/docs/blog/ja/portlet.menu.txt | 114 + .../yiisoft/yii/docs/blog/ja/portlet.tags.txt | 68 + .../yiisoft/yii/docs/blog/ja/post.admin.txt | 109 + .../yiisoft/yii/docs/blog/ja/post.create.txt | 96 + .../yiisoft/yii/docs/blog/ja/post.display.txt | 108 + .../yiisoft/yii/docs/blog/ja/post.model.txt | 224 + .../yii/docs/blog/ja/prototype.auth.txt | 113 + .../yii/docs/blog/ja/prototype.database.txt | 83 + .../yii/docs/blog/ja/prototype.scaffold.txt | 124 + .../yii/docs/blog/ja/prototype.summary.txt | 22 + .../yiisoft/yii/docs/blog/ja/start.design.txt | 56 + .../yii/docs/blog/ja/start.overview.txt | 17 + .../yii/docs/blog/ja/start.requirements.txt | 27 + .../yii/docs/blog/ja/start.testdrive.txt | 97 + .../vendor/yiisoft/yii/docs/blog/ja/toc.txt | 35 + .../yii/docs/blog/pl/comment.admin.txt | 88 + .../yii/docs/blog/pl/comment.create.txt | 165 + .../yii/docs/blog/pl/comment.model.txt | 74 + .../yii/docs/blog/pl/final.deployment.txt | 70 + .../yiisoft/yii/docs/blog/pl/final.future.txt | 57 + .../yii/docs/blog/pl/final.logging.txt | 35 + .../yiisoft/yii/docs/blog/pl/final.url.txt | 45 + .../yii/docs/blog/pl/portlet.comments.txt | 82 + .../yiisoft/yii/docs/blog/pl/portlet.menu.txt | 94 + .../yiisoft/yii/docs/blog/pl/portlet.tags.txt | 62 + .../yiisoft/yii/docs/blog/pl/post.admin.txt | 109 + .../yiisoft/yii/docs/blog/pl/post.create.txt | 96 + .../yiisoft/yii/docs/blog/pl/post.display.txt | 108 + .../yiisoft/yii/docs/blog/pl/post.model.txt | 213 + .../yii/docs/blog/pl/prototype.auth.txt | 105 + .../yii/docs/blog/pl/prototype.database.txt | 70 + .../yii/docs/blog/pl/prototype.scaffold.txt | 117 + .../yii/docs/blog/pl/prototype.summary.txt | 21 + .../yiisoft/yii/docs/blog/pl/start.design.txt | 53 + .../yii/docs/blog/pl/start.overview.txt | 12 + .../yii/docs/blog/pl/start.requirements.txt | 27 + .../yii/docs/blog/pl/start.testdrive.txt | 85 + .../vendor/yiisoft/yii/docs/blog/pl/toc.txt | 35 + .../yii/docs/blog/portlet.comments.txt | 82 + .../yiisoft/yii/docs/blog/portlet.menu.txt | 94 + .../yiisoft/yii/docs/blog/portlet.tags.txt | 62 + .../yiisoft/yii/docs/blog/post.admin.txt | 109 + .../yiisoft/yii/docs/blog/post.create.txt | 96 + .../yiisoft/yii/docs/blog/post.display.txt | 108 + .../yiisoft/yii/docs/blog/post.model.txt | 215 + .../yiisoft/yii/docs/blog/prototype.auth.txt | 105 + .../yii/docs/blog/prototype.database.txt | 70 + .../yii/docs/blog/prototype.scaffold.txt | 118 + .../yii/docs/blog/prototype.summary.txt | 21 + .../yii/docs/blog/pt/comment.admin.txt | 60 + .../yii/docs/blog/pt/start.overview.txt | 10 + .../yii/docs/blog/pt/start.requirements.txt | 28 + .../yii/docs/blog/pt/start.testdrive.txt | 85 + .../vendor/yiisoft/yii/docs/blog/pt/toc.txt | 35 + .../yii/docs/blog/pt_br/comment.admin.txt | 60 + .../yii/docs/blog/pt_br/comment.create.txt | 150 + .../yii/docs/blog/pt_br/start.overview.txt | 12 + .../docs/blog/pt_br/start.requirements.txt | 28 + .../yii/docs/blog/pt_br/start.testdrive.txt | 85 + .../yiisoft/yii/docs/blog/pt_br/toc.txt | 35 + .../yii/docs/blog/ru/comment.admin.txt | 103 + .../yii/docs/blog/ru/comment.create.txt | 191 + .../yii/docs/blog/ru/comment.model.txt | 81 + .../yii/docs/blog/ru/final.deployment.txt | 88 + .../yiisoft/yii/docs/blog/ru/final.future.txt | 87 + .../yii/docs/blog/ru/final.logging.txt | 42 + .../yiisoft/yii/docs/blog/ru/final.url.txt | 60 + .../yii/docs/blog/ru/portlet.comments.txt | 87 + .../yiisoft/yii/docs/blog/ru/portlet.menu.txt | 121 + .../yiisoft/yii/docs/blog/ru/portlet.tags.txt | 68 + .../yiisoft/yii/docs/blog/ru/post.admin.txt | 138 + .../yiisoft/yii/docs/blog/ru/post.create.txt | 123 + .../yiisoft/yii/docs/blog/ru/post.display.txt | 139 + .../yiisoft/yii/docs/blog/ru/post.model.txt | 262 + .../yii/docs/blog/ru/prototype.auth.txt | 162 + .../yii/docs/blog/ru/prototype.database.txt | 101 + .../yii/docs/blog/ru/prototype.scaffold.txt | 160 + .../yii/docs/blog/ru/prototype.summary.txt | 25 + .../yiisoft/yii/docs/blog/ru/start.design.txt | 71 + .../yii/docs/blog/ru/start.overview.txt | 25 + .../yii/docs/blog/ru/start.requirements.txt | 27 + .../yii/docs/blog/ru/start.testdrive.txt | 120 + .../vendor/yiisoft/yii/docs/blog/ru/toc.txt | 33 + .../yiisoft/yii/docs/blog/start.design.txt | 53 + .../yiisoft/yii/docs/blog/start.overview.txt | 13 + .../yii/docs/blog/start.requirements.txt | 27 + .../yiisoft/yii/docs/blog/start.testdrive.txt | 85 + .../lib/vendor/yiisoft/yii/docs/blog/toc.txt | 35 + .../yii/docs/blog/uk/comment.admin.txt | 104 + .../yii/docs/blog/uk/comment.create.txt | 195 + .../yii/docs/blog/uk/comment.model.txt | 80 + .../yii/docs/blog/uk/final.deployment.txt | 89 + .../yiisoft/yii/docs/blog/uk/final.future.txt | 86 + .../yii/docs/blog/uk/final.logging.txt | 44 + .../yiisoft/yii/docs/blog/uk/final.url.txt | 62 + .../yii/docs/blog/uk/portlet.comments.txt | 86 + .../yiisoft/yii/docs/blog/uk/portlet.menu.txt | 118 + .../yiisoft/yii/docs/blog/uk/portlet.tags.txt | 65 + .../yiisoft/yii/docs/blog/uk/post.admin.txt | 139 + .../yiisoft/yii/docs/blog/uk/post.create.txt | 120 + .../yiisoft/yii/docs/blog/uk/post.display.txt | 138 + .../yiisoft/yii/docs/blog/uk/post.model.txt | 254 + .../yii/docs/blog/uk/prototype.auth.txt | 157 + .../yii/docs/blog/uk/prototype.database.txt | 101 + .../yii/docs/blog/uk/prototype.scaffold.txt | 152 + .../yii/docs/blog/uk/prototype.summary.txt | 25 + .../yiisoft/yii/docs/blog/uk/start.design.txt | 53 + .../yii/docs/blog/uk/start.overview.txt | 21 + .../yii/docs/blog/uk/start.requirements.txt | 26 + .../yii/docs/blog/uk/start.testdrive.txt | 104 + .../vendor/yiisoft/yii/docs/blog/uk/toc.txt | 33 + .../yii/docs/blog/zh_cn/comment.admin.txt | 60 + .../yii/docs/blog/zh_cn/comment.create.txt | 150 + .../yii/docs/blog/zh_cn/comment.model.txt | 74 + .../yii/docs/blog/zh_cn/final.deployment.txt | 68 + .../yii/docs/blog/zh_cn/final.future.txt | 57 + .../yii/docs/blog/zh_cn/final.logging.txt | 35 + .../yiisoft/yii/docs/blog/zh_cn/final.url.txt | 45 + .../yii/docs/blog/zh_cn/portlet.comments.txt | 82 + .../yii/docs/blog/zh_cn/portlet.menu.txt | 94 + .../yii/docs/blog/zh_cn/portlet.tags.txt | 62 + .../yii/docs/blog/zh_cn/post.admin.txt | 109 + .../yii/docs/blog/zh_cn/post.create.txt | 96 + .../yii/docs/blog/zh_cn/post.display.txt | 108 + .../yii/docs/blog/zh_cn/post.model.txt | 200 + .../yii/docs/blog/zh_cn/prototype.auth.txt | 105 + .../docs/blog/zh_cn/prototype.database.txt | 70 + .../docs/blog/zh_cn/prototype.scaffold.txt | 118 + .../yii/docs/blog/zh_cn/prototype.summary.txt | 21 + .../yii/docs/blog/zh_cn/start.design.txt | 53 + .../yii/docs/blog/zh_cn/start.overview.txt | 15 + .../docs/blog/zh_cn/start.requirements.txt | 27 + .../yii/docs/blog/zh_cn/start.testdrive.txt | 85 + .../yiisoft/yii/docs/blog/zh_cn/toc.txt | 36 + .../lib/vendor/yiisoft/yii/docs/css/info.gif | Bin 0 -> 698 bytes .../lib/vendor/yiisoft/yii/docs/css/main.css | 477 + .../lib/vendor/yiisoft/yii/docs/css/note.gif | Bin 0 -> 436 bytes .../lib/vendor/yiisoft/yii/docs/css/rtl.css | 34 + .../lib/vendor/yiisoft/yii/docs/css/tip.gif | Bin 0 -> 341 bytes .../yii/docs/guide/basics.application.txt | 234 + .../yii/docs/guide/basics.best-practices.txt | 84 + .../yii/docs/guide/basics.component.txt | 232 + .../yii/docs/guide/basics.controller.txt | 343 + .../yii/docs/guide/basics.convention.txt | 167 + .../yiisoft/yii/docs/guide/basics.entry.txt | 37 + .../yiisoft/yii/docs/guide/basics.model.txt | 28 + .../yiisoft/yii/docs/guide/basics.module.txt | 85 + .../yiisoft/yii/docs/guide/basics.mvc.txt | 54 + .../yii/docs/guide/basics.namespace.txt | 278 + .../yiisoft/yii/docs/guide/basics.view.txt | 149 + .../yii/docs/guide/basics.workflow.txt | 51 + .../yiisoft/yii/docs/guide/caching.data.txt | 255 + .../yii/docs/guide/caching.dynamic.txt | 45 + .../yii/docs/guide/caching.fragment.txt | 170 + .../yii/docs/guide/caching.overview.txt | 85 + .../yiisoft/yii/docs/guide/caching.page.txt | 109 + .../vendor/yiisoft/yii/docs/guide/changes.txt | 98 + .../yiisoft/yii/docs/guide/database.ar.txt | 655 + .../yiisoft/yii/docs/guide/database.arr.txt | 800 + .../yiisoft/yii/docs/guide/database.dao.txt | 266 + .../yii/docs/guide/database.migration.txt | 313 + .../yii/docs/guide/database.overview.txt | 26 + .../yii/docs/guide/database.query-builder.txt | 785 + .../yii/docs/guide/de/basics.application.txt | 233 + .../docs/guide/de/basics.best-practices.txt | 160 + .../yii/docs/guide/de/basics.component.txt | 246 + .../yii/docs/guide/de/basics.controller.txt | 352 + .../yii/docs/guide/de/basics.convention.txt | 167 + .../yii/docs/guide/de/basics.entry.txt | 37 + .../yii/docs/guide/de/basics.model.txt | 29 + .../yii/docs/guide/de/basics.module.txt | 140 + .../yiisoft/yii/docs/guide/de/basics.mvc.txt | 59 + .../yii/docs/guide/de/basics.namespace.txt | 132 + .../yiisoft/yii/docs/guide/de/basics.view.txt | 153 + .../yii/docs/guide/de/basics.workflow.txt | 54 + .../yii/docs/guide/de/caching.data.txt | 249 + .../yii/docs/guide/de/caching.dynamic.txt | 48 + .../yii/docs/guide/de/caching.fragment.txt | 173 + .../yii/docs/guide/de/caching.overview.txt | 88 + .../yii/docs/guide/de/caching.page.txt | 108 + .../yiisoft/yii/docs/guide/de/changes.txt | 101 + .../yiisoft/yii/docs/guide/de/database.ar.txt | 683 + .../yii/docs/guide/de/database.arr.txt | 773 + .../yii/docs/guide/de/database.dao.txt | 268 + .../yii/docs/guide/de/database.migration.txt | 404 + .../yii/docs/guide/de/database.overview.txt | 31 + .../docs/guide/de/database.query-builder.txt | 940 + .../yii/docs/guide/de/extension.create.txt | 264 + .../docs/guide/de/extension.integration.txt | 95 + .../yii/docs/guide/de/extension.overview.txt | 38 + .../yii/docs/guide/de/extension.use.txt | 330 + .../yiisoft/yii/docs/guide/de/form.action.txt | 75 + .../yii/docs/guide/de/form.builder.txt | 539 + .../yiisoft/yii/docs/guide/de/form.model.txt | 380 + .../yii/docs/guide/de/form.overview.txt | 20 + .../yiisoft/yii/docs/guide/de/form.table.txt | 71 + .../yiisoft/yii/docs/guide/de/form.view.txt | 109 + .../yiisoft/yii/docs/guide/de/index.txt | 12 + .../de/quickstart.apache-nginx-config.txt | 94 + .../guide/de/quickstart.first-app-yiic.txt | 103 + .../docs/guide/de/quickstart.first-app.txt | 278 + .../docs/guide/de/quickstart.installation.txt | 31 + .../docs/guide/de/quickstart.what-is-yii.txt | 50 + .../yii/docs/guide/de/test.fixture.txt | 105 + .../yii/docs/guide/de/test.functional.txt | 104 + .../yii/docs/guide/de/test.overview.txt | 156 + .../yiisoft/yii/docs/guide/de/test.unit.txt | 118 + .../vendor/yiisoft/yii/docs/guide/de/toc.txt | 74 + .../yiisoft/yii/docs/guide/de/topics.auth.txt | 683 + .../yii/docs/guide/de/topics.console.txt | 259 + .../yii/docs/guide/de/topics.error.txt | 168 + .../yiisoft/yii/docs/guide/de/topics.gii.txt | 375 + .../yiisoft/yii/docs/guide/de/topics.i18n.txt | 405 + .../yii/docs/guide/de/topics.logging.txt | 237 + .../yii/docs/guide/de/topics.performance.txt | 194 + .../yii/docs/guide/de/topics.prado.txt | 190 + .../yii/docs/guide/de/topics.security.txt | 145 + .../yii/docs/guide/de/topics.theming.txt | 340 + .../yiisoft/yii/docs/guide/de/topics.url.txt | 446 + .../yii/docs/guide/de/topics.webservice.txt | 234 + .../yiisoft/yii/docs/guide/de/upgrade.txt | 67 + .../yii/docs/guide/es/basics.application.txt | 214 + .../yii/docs/guide/es/basics.component.txt | 134 + .../yii/docs/guide/es/basics.controller.txt | 239 + .../yii/docs/guide/es/basics.convention.txt | 140 + .../yii/docs/guide/es/basics.entry.txt | 36 + .../yii/docs/guide/es/basics.model.txt | 30 + .../yiisoft/yii/docs/guide/es/basics.mvc.txt | 52 + .../yiisoft/yii/docs/guide/es/basics.view.txt | 149 + .../yiisoft/yii/docs/guide/es/database.ar.txt | 520 + .../yii/docs/guide/es/database.arr.txt | 355 + .../yii/docs/guide/es/database.dao.txt | 233 + .../yii/docs/guide/es/database.overview.txt | 23 + .../yii/docs/guide/es/extension.overview.txt | 32 + .../yii/docs/guide/es/extension.use.txt | 231 + .../yiisoft/yii/docs/guide/es/index.txt | 11 + .../docs/guide/es/quickstart.first-app.txt | 249 + .../docs/guide/es/quickstart.installation.txt | 32 + .../docs/guide/es/quickstart.what-is-yii.txt | 42 + .../vendor/yiisoft/yii/docs/guide/es/toc.txt | 59 + .../yii/docs/guide/extension.create.txt | 250 + .../yii/docs/guide/extension.integration.txt | 91 + .../yii/docs/guide/extension.overview.txt | 30 + .../yiisoft/yii/docs/guide/extension.use.txt | 319 + .../yiisoft/yii/docs/guide/form.action.txt | 73 + .../yiisoft/yii/docs/guide/form.builder.txt | 495 + .../yiisoft/yii/docs/guide/form.model.txt | 397 + .../yiisoft/yii/docs/guide/form.overview.txt | 19 + .../yiisoft/yii/docs/guide/form.table.txt | 71 + .../yiisoft/yii/docs/guide/form.view.txt | 109 + .../yii/docs/guide/fr/basics.application.txt | 221 + .../docs/guide/fr/basics.best-practices.txt | 93 + .../yii/docs/guide/fr/basics.component.txt | 197 + .../yii/docs/guide/fr/basics.controller.txt | 342 + .../yii/docs/guide/fr/basics.convention.txt | 166 + .../yii/docs/guide/fr/basics.entry.txt | 43 + .../yii/docs/guide/fr/basics.model.txt | 30 + .../yii/docs/guide/fr/basics.module.txt | 127 + .../yiisoft/yii/docs/guide/fr/basics.mvc.txt | 55 + .../yii/docs/guide/fr/basics.namespace.txt | 77 + .../yiisoft/yii/docs/guide/fr/basics.view.txt | 146 + .../yii/docs/guide/fr/basics.workflow.txt | 46 + .../yii/docs/guide/fr/caching.overview.txt | 82 + .../yii/docs/guide/fr/caching.page.txt | 51 + .../yiisoft/yii/docs/guide/fr/database.ar.txt | 655 + .../yii/docs/guide/fr/database.dao.txt | 259 + .../yii/docs/guide/fr/database.overview.txt | 8 + .../yiisoft/yii/docs/guide/fr/form.action.txt | 68 + .../yiisoft/yii/docs/guide/fr/form.model.txt | 426 + .../yii/docs/guide/fr/form.overview.txt | 20 + .../yiisoft/yii/docs/guide/fr/form.table.txt | 70 + .../yiisoft/yii/docs/guide/fr/form.view.txt | 108 + .../yiisoft/yii/docs/guide/fr/index.txt | 9 + .../docs/guide/fr/quickstart.first-app.txt | 248 + .../docs/guide/fr/quickstart.installation.txt | 29 + .../docs/guide/fr/quickstart.what-is-yii.txt | 43 + .../vendor/yiisoft/yii/docs/guide/fr/toc.txt | 74 + .../yii/docs/guide/he/basics.application.txt | 160 + .../yii/docs/guide/he/basics.component.txt | 137 + .../yii/docs/guide/he/basics.controller.txt | 168 + .../yii/docs/guide/he/basics.convention.txt | 90 + .../yii/docs/guide/he/basics.entry.txt | 26 + .../yii/docs/guide/he/basics.model.txt | 14 + .../yii/docs/guide/he/basics.module.txt | 82 + .../yiisoft/yii/docs/guide/he/basics.mvc.txt | 33 + .../yii/docs/guide/he/basics.namespace.txt | 46 + .../yiisoft/yii/docs/guide/he/basics.view.txt | 105 + .../yii/docs/guide/he/basics.workflow.txt | 28 + .../yii/docs/guide/he/caching.data.txt | 78 + .../yii/docs/guide/he/caching.dynamic.txt | 25 + .../yii/docs/guide/he/caching.fragment.txt | 103 + .../yii/docs/guide/he/caching.overview.txt | 59 + .../yii/docs/guide/he/caching.page.txt | 31 + .../yiisoft/yii/docs/guide/he/changes.txt | 120 + .../yiisoft/yii/docs/guide/he/database.ar.txt | 509 + .../yii/docs/guide/he/database.arr.txt | 383 + .../yii/docs/guide/he/database.dao.txt | 195 + .../yii/docs/guide/he/database.overview.txt | 8 + .../yii/docs/guide/he/extension.create.txt | 177 + .../docs/guide/he/extension.integration.txt | 31 + .../yii/docs/guide/he/extension.overview.txt | 23 + .../yii/docs/guide/he/extension.use.txt | 266 + .../yiisoft/yii/docs/guide/he/form.action.txt | 69 + .../yii/docs/guide/he/form.builder.txt | 389 + .../yiisoft/yii/docs/guide/he/form.model.txt | 325 + .../yii/docs/guide/he/form.overview.txt | 17 + .../yiisoft/yii/docs/guide/he/form.table.txt | 74 + .../yiisoft/yii/docs/guide/he/form.view.txt | 88 + .../yiisoft/yii/docs/guide/he/index.txt | 17 + .../guide/he/quickstart.first-app-yiic.txt | 77 + .../docs/guide/he/quickstart.first-app.txt | 204 + .../docs/guide/he/quickstart.installation.txt | 28 + .../docs/guide/he/quickstart.what-is-yii.txt | 26 + .../yii/docs/guide/he/test.fixture.txt | 60 + .../yii/docs/guide/he/test.functional.txt | 67 + .../yii/docs/guide/he/test.overview.txt | 100 + .../yiisoft/yii/docs/guide/he/test.unit.txt | 79 + .../vendor/yiisoft/yii/docs/guide/he/toc.txt | 70 + .../yiisoft/yii/docs/guide/he/topics.auth.txt | 376 + .../yii/docs/guide/he/topics.console.txt | 58 + .../yii/docs/guide/he/topics.error.txt | 104 + .../yiisoft/yii/docs/guide/he/topics.gii.txt | 280 + .../yiisoft/yii/docs/guide/he/topics.i18n.txt | 166 + .../yii/docs/guide/he/topics.logging.txt | 149 + .../yii/docs/guide/he/topics.performance.txt | 111 + .../yii/docs/guide/he/topics.prado.txt | 185 + .../yii/docs/guide/he/topics.security.txt | 93 + .../yii/docs/guide/he/topics.theming.txt | 227 + .../yiisoft/yii/docs/guide/he/topics.url.txt | 262 + .../yii/docs/guide/he/topics.webservice.txt | 173 + .../yiisoft/yii/docs/guide/he/upgrade.txt | 63 + .../yii/docs/guide/hu/basics.application.txt | 210 + .../yii/docs/guide/hu/basics.controller.txt | 245 + .../yii/docs/guide/hu/basics.entry.txt | 38 + .../yii/docs/guide/hu/basics.model.txt | 27 + .../yiisoft/yii/docs/guide/hu/basics.mvc.txt | 59 + .../yiisoft/yii/docs/guide/hu/index.txt | 11 + .../docs/guide/hu/quickstart.first-app.txt | 248 + .../docs/guide/hu/quickstart.installation.txt | 32 + .../docs/guide/hu/quickstart.what-is-yii.txt | 41 + .../vendor/yiisoft/yii/docs/guide/hu/toc.txt | 67 + .../yii/docs/guide/id/basics.application.txt | 219 + .../docs/guide/id/basics.best-practices.txt | 84 + .../yii/docs/guide/id/basics.component.txt | 183 + .../yii/docs/guide/id/basics.controller.txt | 343 + .../yii/docs/guide/id/basics.convention.txt | 167 + .../yii/docs/guide/id/basics.entry.txt | 37 + .../yii/docs/guide/id/basics.model.txt | 27 + .../yii/docs/guide/id/basics.module.txt | 85 + .../yiisoft/yii/docs/guide/id/basics.mvc.txt | 53 + .../yii/docs/guide/id/basics.namespace.txt | 132 + .../yiisoft/yii/docs/guide/id/basics.view.txt | 146 + .../yii/docs/guide/id/basics.workflow.txt | 51 + .../yii/docs/guide/id/caching.data.txt | 255 + .../yii/docs/guide/id/caching.dynamic.txt | 43 + .../yii/docs/guide/id/caching.fragment.txt | 168 + .../yii/docs/guide/id/caching.overview.txt | 84 + .../yii/docs/guide/id/caching.page.txt | 48 + .../yiisoft/yii/docs/guide/id/changes.txt | 85 + .../yiisoft/yii/docs/guide/id/database.ar.txt | 655 + .../yii/docs/guide/id/database.arr.txt | 729 + .../yii/docs/guide/id/database.dao.txt | 266 + .../yii/docs/guide/id/database.migration.txt | 313 + .../yii/docs/guide/id/database.overview.txt | 26 + .../docs/guide/id/database.query-builder.txt | 761 + .../yii/docs/guide/id/extension.create.txt | 250 + .../docs/guide/id/extension.integration.txt | 91 + .../yii/docs/guide/id/extension.overview.txt | 30 + .../yii/docs/guide/id/extension.use.txt | 318 + .../yiisoft/yii/docs/guide/id/form.action.txt | 73 + .../yii/docs/guide/id/form.builder.txt | 485 + .../yiisoft/yii/docs/guide/id/form.model.txt | 381 + .../yii/docs/guide/id/form.overview.txt | 19 + .../yiisoft/yii/docs/guide/id/form.table.txt | 71 + .../yiisoft/yii/docs/guide/id/form.view.txt | 109 + .../yiisoft/yii/docs/guide/id/index.txt | 11 + .../id/quickstart.apache-nginx-config.txt | 78 + .../guide/id/quickstart.first-app-yiic.txt | 95 + .../docs/guide/id/quickstart.first-app.txt | 245 + .../docs/guide/id/quickstart.installation.txt | 31 + .../docs/guide/id/quickstart.what-is-yii.txt | 46 + .../yii/docs/guide/id/test.fixture.txt | 60 + .../yii/docs/guide/id/test.functional.txt | 67 + .../yii/docs/guide/id/test.overview.txt | 101 + .../yiisoft/yii/docs/guide/id/test.unit.txt | 80 + .../vendor/yiisoft/yii/docs/guide/id/toc.txt | 74 + .../yiisoft/yii/docs/guide/id/topics.auth.txt | 596 + .../yii/docs/guide/id/topics.console.txt | 227 + .../yii/docs/guide/id/topics.error.txt | 160 + .../yiisoft/yii/docs/guide/id/topics.gii.txt | 279 + .../yiisoft/yii/docs/guide/id/topics.i18n.txt | 380 + .../yii/docs/guide/id/topics.logging.txt | 217 + .../yii/docs/guide/id/topics.performance.txt | 158 + .../yii/docs/guide/id/topics.prado.txt | 192 + .../yii/docs/guide/id/topics.security.txt | 137 + .../yii/docs/guide/id/topics.theming.txt | 291 + .../yiisoft/yii/docs/guide/id/topics.url.txt | 428 + .../yii/docs/guide/id/topics.webservice.txt | 226 + .../yiisoft/yii/docs/guide/id/upgrade.txt | 63 + .../yiisoft/yii/docs/guide/images/er.png | Bin 0 -> 5870 bytes .../yiisoft/yii/docs/guide/images/er.vsd | Bin 0 -> 80896 bytes .../yii/docs/guide/images/first-app1.png | Bin 0 -> 9027 bytes .../yii/docs/guide/images/first-app2.png | Bin 0 -> 12119 bytes .../yii/docs/guide/images/first-app3.png | Bin 0 -> 14105 bytes .../yii/docs/guide/images/first-app4.png | Bin 0 -> 5184 bytes .../yii/docs/guide/images/first-app5.png | Bin 0 -> 7527 bytes .../yii/docs/guide/images/first-app6.png | Bin 0 -> 68655 bytes .../yii/docs/guide/images/first-app7.png | Bin 0 -> 31854 bytes .../yiisoft/yii/docs/guide/images/flow.png | Bin 0 -> 27851 bytes .../yiisoft/yii/docs/guide/images/flow.vsd | Bin 0 -> 87552 bytes .../yii/docs/guide/images/gii-crud.png | Bin 0 -> 6318 bytes .../yii/docs/guide/images/gii-model.png | Bin 0 -> 48245 bytes .../docs/guide/images/has_many_through.png | Bin 0 -> 4035 bytes .../yii/docs/guide/images/has_one_through.png | Bin 0 -> 3340 bytes .../yiisoft/yii/docs/guide/images/login1.png | Bin 0 -> 1671 bytes .../yiisoft/yii/docs/guide/images/login2.png | Bin 0 -> 3113 bytes .../yii/docs/guide/images/structure.png | Bin 0 -> 6048 bytes .../yii/docs/guide/images/structure.vsd | Bin 0 -> 80896 bytes .../yii/docs/guide/images/through_self.png | Bin 0 -> 2784 bytes .../vendor/yiisoft/yii/docs/guide/index.txt | 11 + .../yii/docs/guide/it/basics.application.txt | 202 + .../docs/guide/it/basics.best-practices.txt | 172 + .../yii/docs/guide/it/basics.component.txt | 188 + .../yii/docs/guide/it/basics.controller.txt | 340 + .../yii/docs/guide/it/basics.convention.txt | 161 + .../yii/docs/guide/it/basics.entry.txt | 38 + .../yii/docs/guide/it/basics.model.txt | 28 + .../yii/docs/guide/it/basics.module.txt | 132 + .../yiisoft/yii/docs/guide/it/basics.mvc.txt | 58 + .../yii/docs/guide/it/basics.namespace.txt | 130 + .../yiisoft/yii/docs/guide/it/basics.view.txt | 145 + .../yii/docs/guide/it/basics.workflow.txt | 51 + .../yii/docs/guide/it/database.overview.txt | 27 + .../yii/docs/guide/it/extension.create.txt | 238 + .../yii/docs/guide/it/extension.overview.txt | 29 + .../yii/docs/guide/it/form.overview.txt | 19 + .../yiisoft/yii/docs/guide/it/index.txt | 12 + .../it/quickstart.apache-nginx-config.txt | 84 + .../guide/it/quickstart.first-app-yiic.txt | 100 + .../docs/guide/it/quickstart.first-app.txt | 256 + .../docs/guide/it/quickstart.installation.txt | 31 + .../docs/guide/it/quickstart.what-is-yii.txt | 50 + .../yii/docs/guide/ja/basics.application.txt | 192 + .../docs/guide/ja/basics.best-practices.txt | 101 + .../yii/docs/guide/ja/basics.component.txt | 217 + .../yii/docs/guide/ja/basics.controller.txt | 312 + .../yii/docs/guide/ja/basics.convention.txt | 143 + .../yii/docs/guide/ja/basics.entry.txt | 33 + .../yii/docs/guide/ja/basics.model.txt | 28 + .../yii/docs/guide/ja/basics.module.txt | 106 + .../yiisoft/yii/docs/guide/ja/basics.mvc.txt | 44 + .../yii/docs/guide/ja/basics.namespace.txt | 252 + .../yiisoft/yii/docs/guide/ja/basics.view.txt | 129 + .../yii/docs/guide/ja/basics.workflow.txt | 35 + .../yii/docs/guide/ja/caching.data.txt | 218 + .../yii/docs/guide/ja/caching.dynamic.txt | 34 + .../yii/docs/guide/ja/caching.fragment.txt | 134 + .../yii/docs/guide/ja/caching.overview.txt | 70 + .../yii/docs/guide/ja/caching.page.txt | 84 + .../yiisoft/yii/docs/guide/ja/changes.txt | 97 + .../yiisoft/yii/docs/guide/ja/database.ar.txt | 587 + .../yii/docs/guide/ja/database.arr.txt | 744 + .../yii/docs/guide/ja/database.dao.txt | 226 + .../yii/docs/guide/ja/database.migration.txt | 348 + .../yii/docs/guide/ja/database.overview.txt | 18 + .../docs/guide/ja/database.query-builder.txt | 918 + .../yii/docs/guide/ja/extension.create.txt | 206 + .../docs/guide/ja/extension.integration.txt | 72 + .../yii/docs/guide/ja/extension.overview.txt | 28 + .../yii/docs/guide/ja/extension.use.txt | 283 + .../yiisoft/yii/docs/guide/ja/form.action.txt | 59 + .../yii/docs/guide/ja/form.builder.txt | 467 + .../yiisoft/yii/docs/guide/ja/form.model.txt | 328 + .../yii/docs/guide/ja/form.overview.txt | 16 + .../yiisoft/yii/docs/guide/ja/form.table.txt | 63 + .../yiisoft/yii/docs/guide/ja/form.view.txt | 100 + .../yiisoft/yii/docs/guide/ja/index.txt | 20 + .../ja/quickstart.apache-nginx-config.txt | 85 + .../guide/ja/quickstart.first-app-yiic.txt | 91 + .../docs/guide/ja/quickstart.first-app.txt | 241 + .../docs/guide/ja/quickstart.installation.txt | 26 + .../docs/guide/ja/quickstart.what-is-yii.txt | 33 + .../yii/docs/guide/ja/test.fixture.txt | 85 + .../yii/docs/guide/ja/test.functional.txt | 86 + .../yii/docs/guide/ja/test.overview.txt | 122 + .../yiisoft/yii/docs/guide/ja/test.unit.txt | 98 + .../vendor/yiisoft/yii/docs/guide/ja/toc.txt | 74 + .../yiisoft/yii/docs/guide/ja/topics.auth.txt | 560 + .../yii/docs/guide/ja/topics.console.txt | 226 + .../yii/docs/guide/ja/topics.error.txt | 122 + .../yiisoft/yii/docs/guide/ja/topics.gii.txt | 345 + .../yiisoft/yii/docs/guide/ja/topics.i18n.txt | 307 + .../yii/docs/guide/ja/topics.logging.txt | 232 + .../yii/docs/guide/ja/topics.performance.txt | 160 + .../yii/docs/guide/ja/topics.prado.txt | 174 + .../yii/docs/guide/ja/topics.security.txt | 106 + .../yii/docs/guide/ja/topics.theming.txt | 281 + .../yiisoft/yii/docs/guide/ja/topics.url.txt | 368 + .../yii/docs/guide/ja/topics.webservice.txt | 194 + .../yiisoft/yii/docs/guide/ja/upgrade.txt | 54 + .../yiisoft/yii/docs/guide/nl/changes.txt | 77 + .../yiisoft/yii/docs/guide/nl/index.txt | 14 + .../docs/guide/nl/quickstart.first-app.txt | 247 + .../docs/guide/nl/quickstart.installation.txt | 32 + .../docs/guide/nl/quickstart.what-is-yii.txt | 43 + .../yiisoft/yii/docs/guide/nl/upgrade.txt | 70 + .../yii/docs/guide/no/database.dao.txt | 239 + .../yii/docs/guide/no/database.overview.txt | 18 + .../docs/guide/no/quickstart.first-app.txt | 241 + .../docs/guide/no/quickstart.installation.txt | 31 + .../docs/guide/no/quickstart.what-is-yii.txt | 41 + .../vendor/yiisoft/yii/docs/guide/no/toc.txt | 59 + .../yii/docs/guide/pl/basics.application.txt | 217 + .../docs/guide/pl/basics.best-practices.txt | 84 + .../yii/docs/guide/pl/basics.component.txt | 188 + .../yii/docs/guide/pl/basics.controller.txt | 329 + .../yii/docs/guide/pl/basics.convention.txt | 150 + .../yii/docs/guide/pl/basics.entry.txt | 36 + .../yii/docs/guide/pl/basics.model.txt | 28 + .../yii/docs/guide/pl/basics.module.txt | 124 + .../yiisoft/yii/docs/guide/pl/basics.mvc.txt | 53 + .../yii/docs/guide/pl/basics.namespace.txt | 125 + .../yiisoft/yii/docs/guide/pl/basics.view.txt | 147 + .../yii/docs/guide/pl/basics.workflow.txt | 49 + .../yii/docs/guide/pl/caching.data.txt | 250 + .../yii/docs/guide/pl/caching.dynamic.txt | 43 + .../yii/docs/guide/pl/caching.fragment.txt | 167 + .../yii/docs/guide/pl/caching.overview.txt | 81 + .../yii/docs/guide/pl/caching.page.txt | 48 + .../yiisoft/yii/docs/guide/pl/changes.txt | 88 + .../yiisoft/yii/docs/guide/pl/database.ar.txt | 639 + .../yii/docs/guide/pl/database.arr.txt | 735 + .../yii/docs/guide/pl/database.dao.txt | 255 + .../yii/docs/guide/pl/database.migration.txt | 313 + .../yii/docs/guide/pl/database.overview.txt | 28 + .../docs/guide/pl/database.query-builder.txt | 760 + .../yii/docs/guide/pl/extension.create.txt | 247 + .../docs/guide/pl/extension.integration.txt | 87 + .../yii/docs/guide/pl/extension.overview.txt | 34 + .../yii/docs/guide/pl/extension.use.txt | 313 + .../yiisoft/yii/docs/guide/pl/form.action.txt | 71 + .../yii/docs/guide/pl/form.builder.txt | 506 + .../yiisoft/yii/docs/guide/pl/form.model.txt | 374 + .../yii/docs/guide/pl/form.overview.txt | 18 + .../yiisoft/yii/docs/guide/pl/form.table.txt | 71 + .../yiisoft/yii/docs/guide/pl/form.view.txt | 106 + .../yiisoft/yii/docs/guide/pl/index.txt | 11 + .../pl/quickstart.apache-nginx-config.txt | 78 + .../guide/pl/quickstart.first-app-yiic.txt | 96 + .../docs/guide/pl/quickstart.first-app.txt | 250 + .../docs/guide/pl/quickstart.installation.txt | 31 + .../docs/guide/pl/quickstart.what-is-yii.txt | 45 + .../yii/docs/guide/pl/test.fixture.txt | 60 + .../yii/docs/guide/pl/test.functional.txt | 97 + .../yii/docs/guide/pl/test.overview.txt | 146 + .../yiisoft/yii/docs/guide/pl/test.unit.txt | 112 + .../vendor/yiisoft/yii/docs/guide/pl/toc.txt | 74 + .../yiisoft/yii/docs/guide/pl/topics.auth.txt | 600 + .../yii/docs/guide/pl/topics.console.txt | 225 + .../yii/docs/guide/pl/topics.error.txt | 149 + .../yiisoft/yii/docs/guide/pl/topics.gii.txt | 279 + .../yiisoft/yii/docs/guide/pl/topics.i18n.txt | 355 + .../yii/docs/guide/pl/topics.logging.txt | 215 + .../yii/docs/guide/pl/topics.performance.txt | 172 + .../yii/docs/guide/pl/topics.prado.txt | 183 + .../yii/docs/guide/pl/topics.security.txt | 141 + .../yii/docs/guide/pl/topics.theming.txt | 313 + .../yiisoft/yii/docs/guide/pl/topics.url.txt | 422 + .../yii/docs/guide/pl/topics.webservice.txt | 226 + .../yiisoft/yii/docs/guide/pl/upgrade.txt | 57 + .../yii/docs/guide/pt/basics.application.txt | 215 + .../yii/docs/guide/pt/basics.component.txt | 180 + .../yii/docs/guide/pt/basics.controller.txt | 235 + .../yii/docs/guide/pt/basics.convention.txt | 167 + .../yii/docs/guide/pt/basics.entry.txt | 37 + .../yii/docs/guide/pt/basics.model.txt | 27 + .../yiisoft/yii/docs/guide/pt/basics.mvc.txt | 51 + .../yii/docs/guide/pt/basics.namespace.txt | 73 + .../yiisoft/yii/docs/guide/pt/basics.view.txt | 146 + .../yii/docs/guide/pt/basics.workflow.txt | 44 + .../yii/docs/guide/pt/caching.data.txt | 114 + .../yii/docs/guide/pt/caching.dynamic.txt | 44 + .../yii/docs/guide/pt/caching.fragment.txt | 154 + .../yii/docs/guide/pt/caching.overview.txt | 87 + .../yii/docs/guide/pt/caching.page.txt | 47 + .../yiisoft/yii/docs/guide/pt/database.ar.txt | 659 + .../yii/docs/guide/pt/database.arr.txt | 520 + .../yii/docs/guide/pt/database.dao.txt | 265 + .../yii/docs/guide/pt/database.overview.txt | 22 + .../yii/docs/guide/pt/extension.overview.txt | 34 + .../yii/docs/guide/pt/extension.use.txt | 323 + .../yiisoft/yii/docs/guide/pt/form.action.txt | 73 + .../yiisoft/yii/docs/guide/pt/form.model.txt | 419 + .../yii/docs/guide/pt/form.overview.txt | 19 + .../yiisoft/yii/docs/guide/pt/form.table.txt | 70 + .../yiisoft/yii/docs/guide/pt/form.view.txt | 112 + .../yiisoft/yii/docs/guide/pt/index.txt | 13 + .../docs/guide/pt/quickstart.first-app.txt | 249 + .../docs/guide/pt/quickstart.installation.txt | 30 + .../docs/guide/pt/quickstart.what-is-yii.txt | 42 + .../vendor/yiisoft/yii/docs/guide/pt/toc.txt | 73 + .../yii/docs/guide/pt/topics.console.txt | 226 + .../yii/docs/guide/pt/topics.webservice.txt | 227 + .../docs/guide/pt_br/basics.application.txt | 216 + .../guide/pt_br/basics.best-practices.txt | 84 + .../yii/docs/guide/pt_br/basics.component.txt | 180 + .../docs/guide/pt_br/basics.controller.txt | 235 + .../docs/guide/pt_br/basics.convention.txt | 167 + .../yii/docs/guide/pt_br/basics.entry.txt | 37 + .../yii/docs/guide/pt_br/basics.model.txt | 27 + .../yii/docs/guide/pt_br/basics.module.txt | 85 + .../yii/docs/guide/pt_br/basics.mvc.txt | 51 + .../yii/docs/guide/pt_br/basics.namespace.txt | 274 + .../yii/docs/guide/pt_br/basics.view.txt | 150 + .../yii/docs/guide/pt_br/basics.workflow.txt | 44 + .../yii/docs/guide/pt_br/caching.data.txt | 114 + .../yii/docs/guide/pt_br/caching.dynamic.txt | 44 + .../yii/docs/guide/pt_br/caching.fragment.txt | 156 + .../yii/docs/guide/pt_br/caching.overview.txt | 87 + .../yii/docs/guide/pt_br/caching.page.txt | 47 + .../yiisoft/yii/docs/guide/pt_br/changes.txt | 86 + .../yii/docs/guide/pt_br/database.ar.txt | 659 + .../yii/docs/guide/pt_br/database.arr.txt | 520 + .../yii/docs/guide/pt_br/database.dao.txt | 265 + .../docs/guide/pt_br/database.migration.txt | 313 + .../docs/guide/pt_br/database.overview.txt | 22 + .../guide/pt_br/database.query-builder.txt | 783 + .../yii/docs/guide/pt_br/extension.create.txt | 265 + .../guide/pt_br/extension.integration.txt | 98 + .../docs/guide/pt_br/extension.overview.txt | 34 + .../yii/docs/guide/pt_br/extension.use.txt | 324 + .../yii/docs/guide/pt_br/form.action.txt | 73 + .../yii/docs/guide/pt_br/form.model.txt | 419 + .../yii/docs/guide/pt_br/form.overview.txt | 19 + .../yii/docs/guide/pt_br/form.table.txt | 70 + .../yii/docs/guide/pt_br/form.view.txt | 112 + .../yiisoft/yii/docs/guide/pt_br/index.txt | 13 + .../guide/pt_br/quickstart.first-app-yiic.txt | 100 + .../docs/guide/pt_br/quickstart.first-app.txt | 270 + .../guide/pt_br/quickstart.installation.txt | 30 + .../guide/pt_br/quickstart.what-is-yii.txt | 42 + .../yii/docs/guide/pt_br/test.fixture.txt | 112 + .../yii/docs/guide/pt_br/test.functional.txt | 104 + .../yii/docs/guide/pt_br/test.overview.txt | 157 + .../yii/docs/guide/pt_br/test.unit.txt | 120 + .../yiisoft/yii/docs/guide/pt_br/toc.txt | 74 + .../yii/docs/guide/pt_br/topics.auth.txt | 584 + .../yii/docs/guide/pt_br/topics.console.txt | 226 + .../docs/guide/pt_br/topics.webservice.txt | 227 + .../yiisoft/yii/docs/guide/pt_br/upgrade.txt | 67 + .../guide/quickstart.apache-nginx-config.txt | 83 + .../docs/guide/quickstart.first-app-yiic.txt | 99 + .../yii/docs/guide/quickstart.first-app.txt | 258 + .../docs/guide/quickstart.installation.txt | 31 + .../yii/docs/guide/quickstart.what-is-yii.txt | 46 + .../yii/docs/guide/ro/basics.application.txt | 190 + .../yii/docs/guide/ro/basics.component.txt | 163 + .../yii/docs/guide/ro/basics.controller.txt | 222 + .../yii/docs/guide/ro/basics.convention.txt | 137 + .../yii/docs/guide/ro/basics.entry.txt | 35 + .../yii/docs/guide/ro/basics.model.txt | 27 + .../yii/docs/guide/ro/basics.module.txt | 128 + .../yiisoft/yii/docs/guide/ro/basics.mvc.txt | 50 + .../yii/docs/guide/ro/basics.namespace.txt | 68 + .../yiisoft/yii/docs/guide/ro/basics.view.txt | 142 + .../yii/docs/guide/ro/basics.workflow.txt | 41 + .../yii/docs/guide/ro/caching.data.txt | 103 + .../yii/docs/guide/ro/caching.dynamic.txt | 47 + .../yii/docs/guide/ro/caching.fragment.txt | 155 + .../yii/docs/guide/ro/caching.overview.txt | 71 + .../yii/docs/guide/ro/caching.page.txt | 51 + .../yiisoft/yii/docs/guide/ro/database.ar.txt | 496 + .../yii/docs/guide/ro/database.arr.txt | 360 + .../yii/docs/guide/ro/database.dao.txt | 233 + .../yii/docs/guide/ro/database.overview.txt | 18 + .../yii/docs/guide/ro/extension.create.txt | 211 + .../docs/guide/ro/extension.integration.txt | 46 + .../yii/docs/guide/ro/extension.overview.txt | 33 + .../yii/docs/guide/ro/extension.use.txt | 227 + .../yiisoft/yii/docs/guide/ro/form.action.txt | 71 + .../yiisoft/yii/docs/guide/ro/form.model.txt | 345 + .../yii/docs/guide/ro/form.overview.txt | 19 + .../yiisoft/yii/docs/guide/ro/form.table.txt | 69 + .../yiisoft/yii/docs/guide/ro/form.view.txt | 70 + .../yiisoft/yii/docs/guide/ro/index.txt | 13 + .../docs/guide/ro/quickstart.first-app.txt | 240 + .../docs/guide/ro/quickstart.installation.txt | 33 + .../docs/guide/ro/quickstart.what-is-yii.txt | 39 + .../vendor/yiisoft/yii/docs/guide/ro/toc.txt | 59 + .../yiisoft/yii/docs/guide/ro/topics.auth.txt | 543 + .../yii/docs/guide/ru/basics.application.txt | 208 + .../docs/guide/ru/basics.best-practices.txt | 141 + .../yii/docs/guide/ru/basics.component.txt | 221 + .../yii/docs/guide/ru/basics.controller.txt | 325 + .../yii/docs/guide/ru/basics.convention.txt | 134 + .../yii/docs/guide/ru/basics.entry.txt | 36 + .../yii/docs/guide/ru/basics.model.txt | 29 + .../yii/docs/guide/ru/basics.module.txt | 114 + .../yiisoft/yii/docs/guide/ru/basics.mvc.txt | 44 + .../yii/docs/guide/ru/basics.namespace.txt | 268 + .../yiisoft/yii/docs/guide/ru/basics.view.txt | 149 + .../yii/docs/guide/ru/basics.workflow.txt | 37 + .../yii/docs/guide/ru/caching.data.txt | 257 + .../yii/docs/guide/ru/caching.dynamic.txt | 44 + .../yii/docs/guide/ru/caching.fragment.txt | 174 + .../yii/docs/guide/ru/caching.overview.txt | 90 + .../yii/docs/guide/ru/caching.page.txt | 117 + .../yiisoft/yii/docs/guide/ru/changes.txt | 99 + .../yiisoft/yii/docs/guide/ru/database.ar.txt | 628 + .../yii/docs/guide/ru/database.arr.txt | 759 + .../yii/docs/guide/ru/database.dao.txt | 242 + .../yii/docs/guide/ru/database.migration.txt | 388 + .../yii/docs/guide/ru/database.overview.txt | 25 + .../docs/guide/ru/database.query-builder.txt | 921 + .../yii/docs/guide/ru/extension.create.txt | 219 + .../docs/guide/ru/extension.integration.txt | 84 + .../yii/docs/guide/ru/extension.overview.txt | 26 + .../yii/docs/guide/ru/extension.use.txt | 310 + .../yiisoft/yii/docs/guide/ru/form.action.txt | 67 + .../yii/docs/guide/ru/form.builder.txt | 498 + .../yiisoft/yii/docs/guide/ru/form.model.txt | 372 + .../yii/docs/guide/ru/form.overview.txt | 17 + .../yiisoft/yii/docs/guide/ru/form.table.txt | 66 + .../yiisoft/yii/docs/guide/ru/form.view.txt | 101 + .../yiisoft/yii/docs/guide/ru/index.txt | 16 + .../ru/quickstart.apache-nginx-config.txt | 88 + .../guide/ru/quickstart.first-app-yiic.txt | 89 + .../docs/guide/ru/quickstart.first-app.txt | 250 + .../docs/guide/ru/quickstart.installation.txt | 27 + .../docs/guide/ru/quickstart.what-is-yii.txt | 39 + .../yii/docs/guide/ru/test.fixture.txt | 106 + .../yii/docs/guide/ru/test.functional.txt | 102 + .../yii/docs/guide/ru/test.overview.txt | 133 + .../yiisoft/yii/docs/guide/ru/test.unit.txt | 115 + .../vendor/yiisoft/yii/docs/guide/ru/toc.txt | 72 + .../yiisoft/yii/docs/guide/ru/topics.auth.txt | 623 + .../yii/docs/guide/ru/topics.console.txt | 253 + .../yii/docs/guide/ru/topics.error.txt | 141 + .../yiisoft/yii/docs/guide/ru/topics.gii.txt | 366 + .../yiisoft/yii/docs/guide/ru/topics.i18n.txt | 336 + .../yii/docs/guide/ru/topics.logging.txt | 246 + .../yii/docs/guide/ru/topics.performance.txt | 190 + .../yii/docs/guide/ru/topics.prado.txt | 182 + .../yii/docs/guide/ru/topics.security.txt | 122 + .../yii/docs/guide/ru/topics.theming.txt | 304 + .../yiisoft/yii/docs/guide/ru/topics.url.txt | 413 + .../yii/docs/guide/ru/topics.webservice.txt | 211 + .../yiisoft/yii/docs/guide/ru/upgrade.txt | 66 + .../yii/docs/guide/sv/basics.application.txt | 199 + .../docs/guide/sv/basics.best-practices.txt | 137 + .../yii/docs/guide/sv/basics.component.txt | 189 + .../yii/docs/guide/sv/basics.controller.txt | 324 + .../yii/docs/guide/sv/basics.convention.txt | 139 + .../yii/docs/guide/sv/basics.entry.txt | 35 + .../yii/docs/guide/sv/basics.model.txt | 27 + .../yii/docs/guide/sv/basics.module.txt | 121 + .../yiisoft/yii/docs/guide/sv/basics.mvc.txt | 68 + .../yii/docs/guide/sv/basics.namespace.txt | 131 + .../yiisoft/yii/docs/guide/sv/basics.view.txt | 148 + .../yii/docs/guide/sv/basics.workflow.txt | 49 + .../yii/docs/guide/sv/caching.data.txt | 243 + .../yii/docs/guide/sv/caching.dynamic.txt | 45 + .../yii/docs/guide/sv/caching.fragment.txt | 156 + .../yii/docs/guide/sv/caching.overview.txt | 81 + .../yii/docs/guide/sv/caching.page.txt | 48 + .../yiisoft/yii/docs/guide/sv/database.ar.txt | 673 + .../yii/docs/guide/sv/database.arr.txt | 775 + .../yii/docs/guide/sv/database.dao.txt | 265 + .../yii/docs/guide/sv/database.migration.txt | 376 + .../yii/docs/guide/sv/database.overview.txt | 26 + .../docs/guide/sv/database.query-builder.txt | 910 + .../yii/docs/guide/sv/extension.create.txt | 273 + .../docs/guide/sv/extension.integration.txt | 91 + .../yii/docs/guide/sv/extension.overview.txt | 27 + .../yii/docs/guide/sv/extension.use.txt | 330 + .../yiisoft/yii/docs/guide/sv/form.action.txt | 73 + .../yii/docs/guide/sv/form.builder.txt | 500 + .../yiisoft/yii/docs/guide/sv/form.model.txt | 385 + .../yii/docs/guide/sv/form.overview.txt | 19 + .../yiisoft/yii/docs/guide/sv/form.table.txt | 71 + .../yiisoft/yii/docs/guide/sv/form.view.txt | 109 + .../yiisoft/yii/docs/guide/sv/index.txt | 12 + .../sv/quickstart.apache-nginx-config.txt | 84 + .../guide/sv/quickstart.first-app-yiic.txt | 96 + .../docs/guide/sv/quickstart.first-app.txt | 251 + .../docs/guide/sv/quickstart.installation.txt | 30 + .../docs/guide/sv/quickstart.what-is-yii.txt | 46 + .../yii/docs/guide/sv/test.fixture.txt | 104 + .../yii/docs/guide/sv/test.functional.txt | 97 + .../yii/docs/guide/sv/test.overview.txt | 144 + .../yiisoft/yii/docs/guide/sv/test.unit.txt | 110 + .../vendor/yiisoft/yii/docs/guide/sv/toc.txt | 74 + .../yiisoft/yii/docs/guide/sv/topics.auth.txt | 660 + .../yii/docs/guide/sv/topics.console.txt | 233 + .../yii/docs/guide/sv/topics.error.txt | 161 + .../yiisoft/yii/docs/guide/sv/topics.gii.txt | 349 + .../yiisoft/yii/docs/guide/sv/topics.i18n.txt | 367 + .../yii/docs/guide/sv/topics.logging.txt | 223 + .../yii/docs/guide/sv/topics.performance.txt | 173 + .../yii/docs/guide/sv/topics.prado.txt | 188 + .../yii/docs/guide/sv/topics.security.txt | 145 + .../yii/docs/guide/sv/topics.theming.txt | 317 + .../yiisoft/yii/docs/guide/sv/topics.url.txt | 432 + .../yii/docs/guide/sv/topics.webservice.txt | 225 + .../yiisoft/yii/docs/guide/test.fixture.txt | 60 + .../yii/docs/guide/test.functional.txt | 67 + .../yiisoft/yii/docs/guide/test.overview.txt | 101 + .../yiisoft/yii/docs/guide/test.unit.txt | 80 + .../lib/vendor/yiisoft/yii/docs/guide/toc.txt | 74 + .../yiisoft/yii/docs/guide/topics.auth.txt | 611 + .../yiisoft/yii/docs/guide/topics.console.txt | 255 + .../yiisoft/yii/docs/guide/topics.error.txt | 160 + .../yiisoft/yii/docs/guide/topics.gii.txt | 280 + .../yiisoft/yii/docs/guide/topics.i18n.txt | 384 + .../yiisoft/yii/docs/guide/topics.logging.txt | 259 + .../yii/docs/guide/topics.performance.txt | 180 + .../yiisoft/yii/docs/guide/topics.prado.txt | 192 + .../yii/docs/guide/topics.security.txt | 138 + .../yiisoft/yii/docs/guide/topics.theming.txt | 291 + .../yiisoft/yii/docs/guide/topics.url.txt | 438 + .../yii/docs/guide/topics.webservice.txt | 225 + .../yii/docs/guide/uk/basics.application.txt | 208 + .../docs/guide/uk/basics.best-practices.txt | 135 + .../yii/docs/guide/uk/basics.component.txt | 225 + .../yii/docs/guide/uk/basics.controller.txt | 321 + .../yii/docs/guide/uk/basics.convention.txt | 141 + .../yii/docs/guide/uk/basics.entry.txt | 26 + .../yii/docs/guide/uk/basics.model.txt | 29 + .../yii/docs/guide/uk/basics.module.txt | 121 + .../yiisoft/yii/docs/guide/uk/basics.mvc.txt | 45 + .../yii/docs/guide/uk/basics.namespace.txt | 267 + .../yiisoft/yii/docs/guide/uk/basics.view.txt | 146 + .../yii/docs/guide/uk/basics.workflow.txt | 40 + .../yii/docs/guide/uk/caching.data.txt | 184 + .../yii/docs/guide/uk/caching.dynamic.txt | 23 + .../yii/docs/guide/uk/caching.fragment.txt | 112 + .../yii/docs/guide/uk/caching.overview.txt | 75 + .../yii/docs/guide/uk/caching.page.txt | 83 + .../yiisoft/yii/docs/guide/uk/changes.txt | 97 + .../yiisoft/yii/docs/guide/uk/database.ar.txt | 492 + .../yii/docs/guide/uk/database.arr.txt | 765 + .../yii/docs/guide/uk/database.dao.txt | 204 + .../yii/docs/guide/uk/database.migration.txt | 295 + .../yii/docs/guide/uk/database.overview.txt | 15 + .../docs/guide/uk/database.query-builder.txt | 875 + .../yii/docs/guide/uk/extension.create.txt | 172 + .../docs/guide/uk/extension.integration.txt | 60 + .../yii/docs/guide/uk/extension.overview.txt | 19 + .../yii/docs/guide/uk/extension.use.txt | 259 + .../yiisoft/yii/docs/guide/uk/form.action.txt | 56 + .../yii/docs/guide/uk/form.builder.txt | 418 + .../yiisoft/yii/docs/guide/uk/form.model.txt | 358 + .../yii/docs/guide/uk/form.overview.txt | 17 + .../yiisoft/yii/docs/guide/uk/form.table.txt | 57 + .../yiisoft/yii/docs/guide/uk/form.view.txt | 94 + .../yiisoft/yii/docs/guide/uk/index.txt | 12 + .../uk/quickstart.apache-nginx-config.txt | 89 + .../guide/uk/quickstart.first-app-yiic.txt | 76 + .../docs/guide/uk/quickstart.first-app.txt | 251 + .../docs/guide/uk/quickstart.installation.txt | 27 + .../docs/guide/uk/quickstart.what-is-yii.txt | 39 + .../yii/docs/guide/uk/test.fixture.txt | 58 + .../yii/docs/guide/uk/test.functional.txt | 65 + .../yii/docs/guide/uk/test.overview.txt | 95 + .../yiisoft/yii/docs/guide/uk/test.unit.txt | 76 + .../vendor/yiisoft/yii/docs/guide/uk/toc.txt | 72 + .../yiisoft/yii/docs/guide/uk/topics.auth.txt | 501 + .../yii/docs/guide/uk/topics.console.txt | 233 + .../yii/docs/guide/uk/topics.error.txt | 133 + .../yiisoft/yii/docs/guide/uk/topics.gii.txt | 342 + .../yiisoft/yii/docs/guide/uk/topics.i18n.txt | 310 + .../yii/docs/guide/uk/topics.logging.txt | 233 + .../yii/docs/guide/uk/topics.performance.txt | 121 + .../yii/docs/guide/uk/topics.prado.txt | 169 + .../yii/docs/guide/uk/topics.security.txt | 92 + .../yii/docs/guide/uk/topics.theming.txt | 276 + .../yiisoft/yii/docs/guide/uk/topics.url.txt | 295 + .../yii/docs/guide/uk/topics.webservice.txt | 204 + .../yiisoft/yii/docs/guide/uk/upgrade.txt | 66 + .../vendor/yiisoft/yii/docs/guide/upgrade.txt | 64 + .../yii/docs/guide/vi/basics.entry.txt | 34 + .../yiisoft/yii/docs/guide/vi/index.txt | 11 + .../docs/guide/vi/quickstart.first-app.txt | 252 + .../docs/guide/vi/quickstart.installation.txt | 31 + .../docs/guide/vi/quickstart.what-is-yii.txt | 38 + .../vendor/yiisoft/yii/docs/guide/vi/toc.txt | 68 + .../docs/guide/zh_cn/basics.application.txt | 176 + .../yii/docs/guide/zh_cn/basics.component.txt | 156 + .../docs/guide/zh_cn/basics.controller.txt | 270 + .../docs/guide/zh_cn/basics.convention.txt | 129 + .../yii/docs/guide/zh_cn/basics.entry.txt | 29 + .../yii/docs/guide/zh_cn/basics.model.txt | 20 + .../yii/docs/guide/zh_cn/basics.module.txt | 100 + .../yii/docs/guide/zh_cn/basics.mvc.txt | 42 + .../yii/docs/guide/zh_cn/basics.namespace.txt | 105 + .../yii/docs/guide/zh_cn/basics.view.txt | 100 + .../yii/docs/guide/zh_cn/basics.workflow.txt | 37 + .../yii/docs/guide/zh_cn/caching.data.txt | 87 + .../yii/docs/guide/zh_cn/caching.dynamic.txt | 29 + .../yii/docs/guide/zh_cn/caching.fragment.txt | 106 + .../yii/docs/guide/zh_cn/caching.overview.txt | 63 + .../yii/docs/guide/zh_cn/caching.page.txt | 38 + .../yiisoft/yii/docs/guide/zh_cn/changes.txt | 153 + .../yii/docs/guide/zh_cn/database.ar.txt | 592 + .../yii/docs/guide/zh_cn/database.arr.txt | 486 + .../yii/docs/guide/zh_cn/database.dao.txt | 231 + .../docs/guide/zh_cn/database.overview.txt | 8 + .../yii/docs/guide/zh_cn/extension.create.txt | 191 + .../guide/zh_cn/extension.integration.txt | 29 + .../docs/guide/zh_cn/extension.overview.txt | 21 + .../yii/docs/guide/zh_cn/extension.use.txt | 284 + .../yii/docs/guide/zh_cn/form.action.txt | 61 + .../yii/docs/guide/zh_cn/form.builder.txt | 446 + .../yii/docs/guide/zh_cn/form.model.txt | 360 + .../yii/docs/guide/zh_cn/form.overview.txt | 16 + .../yii/docs/guide/zh_cn/form.table.txt | 64 + .../yii/docs/guide/zh_cn/form.view.txt | 98 + .../yiisoft/yii/docs/guide/zh_cn/index.txt | 27 + .../docs/guide/zh_cn/quickstart.first-app.txt | 204 + .../guide/zh_cn/quickstart.installation.txt | 22 + .../guide/zh_cn/quickstart.what-is-yii.txt | 36 + .../yii/docs/guide/zh_cn/test.fixture.txt | 60 + .../yii/docs/guide/zh_cn/test.overview.txt | 101 + .../yiisoft/yii/docs/guide/zh_cn/toc.txt | 73 + .../yii/docs/guide/zh_cn/topics.auth.txt | 489 + .../yii/docs/guide/zh_cn/topics.error.txt | 96 + .../yii/docs/guide/zh_cn/topics.gii.txt | 279 + .../yii/docs/guide/zh_cn/topics.i18n.txt | 221 + .../yii/docs/guide/zh_cn/topics.logging.txt | 208 + .../docs/guide/zh_cn/topics.performance.txt | 114 + .../yii/docs/guide/zh_cn/topics.security.txt | 108 + .../yii/docs/guide/zh_cn/topics.theming.txt | 250 + .../yii/docs/guide/zh_cn/topics.url.txt | 313 + .../docs/guide/zh_cn/topics.webservice.txt | 171 + .../yiisoft/yii/docs/guide/zh_cn/upgrade.txt | 41 + .../docs/guide/zh_tw/basics.application.txt | 176 + .../guide/zh_tw/basics.best-practices.txt | 84 + .../yii/docs/guide/zh_tw/basics.component.txt | 156 + .../docs/guide/zh_tw/basics.controller.txt | 276 + .../docs/guide/zh_tw/basics.convention.txt | 128 + .../yii/docs/guide/zh_tw/basics.entry.txt | 29 + .../yii/docs/guide/zh_tw/basics.model.txt | 20 + .../yii/docs/guide/zh_tw/basics.module.txt | 100 + .../yii/docs/guide/zh_tw/basics.mvc.txt | 42 + .../yii/docs/guide/zh_tw/basics.namespace.txt | 239 + .../yii/docs/guide/zh_tw/basics.view.txt | 100 + .../yii/docs/guide/zh_tw/basics.workflow.txt | 37 + .../yii/docs/guide/zh_tw/caching.data.txt | 196 + .../yii/docs/guide/zh_tw/caching.dynamic.txt | 25 + .../yii/docs/guide/zh_tw/caching.fragment.txt | 104 + .../yii/docs/guide/zh_tw/caching.overview.txt | 63 + .../yii/docs/guide/zh_tw/caching.page.txt | 70 + .../yiisoft/yii/docs/guide/zh_tw/changes.txt | 88 + .../yii/docs/guide/zh_tw/database.ar.txt | 529 + .../yii/docs/guide/zh_tw/database.arr.txt | 599 + .../yii/docs/guide/zh_tw/database.dao.txt | 233 + .../docs/guide/zh_tw/database.overview.txt | 10 + .../yii/docs/guide/zh_tw/extension.create.txt | 179 + .../guide/zh_tw/extension.integration.txt | 29 + .../docs/guide/zh_tw/extension.overview.txt | 21 + .../yii/docs/guide/zh_tw/extension.use.txt | 267 + .../yii/docs/guide/zh_tw/form.action.txt | 61 + .../yii/docs/guide/zh_tw/form.builder.txt | 445 + .../yii/docs/guide/zh_tw/form.model.txt | 313 + .../yii/docs/guide/zh_tw/form.overview.txt | 16 + .../yii/docs/guide/zh_tw/form.table.txt | 64 + .../yii/docs/guide/zh_tw/form.view.txt | 98 + .../yiisoft/yii/docs/guide/zh_tw/index.txt | 13 + .../docs/guide/zh_tw/quickstart.first-app.txt | 206 + .../guide/zh_tw/quickstart.installation.txt | 22 + .../guide/zh_tw/quickstart.what-is-yii.txt | 36 + .../yii/docs/guide/zh_tw/test.fixture.txt | 60 + .../yii/docs/guide/zh_tw/test.overview.txt | 101 + .../yiisoft/yii/docs/guide/zh_tw/toc.txt | 72 + .../yii/docs/guide/zh_tw/topics.auth.txt | 431 + .../yii/docs/guide/zh_tw/topics.error.txt | 99 + .../yii/docs/guide/zh_tw/topics.gii.txt | 280 + .../yii/docs/guide/zh_tw/topics.i18n.txt | 222 + .../yii/docs/guide/zh_tw/topics.logging.txt | 186 + .../docs/guide/zh_tw/topics.performance.txt | 118 + .../yii/docs/guide/zh_tw/topics.security.txt | 108 + .../yii/docs/guide/zh_tw/topics.theming.txt | 231 + .../yii/docs/guide/zh_tw/topics.url.txt | 287 + .../docs/guide/zh_tw/topics.webservice.txt | 177 + .../yiisoft/yii/docs/guide/zh_tw/upgrade.txt | 42 + .../lib/vendor/yiisoft/yii/docs/index.php | 6 + .../vendor/yiisoft/yii/docs/viewer/.htaccess | 1 + .../docs/viewer/components/MarkdownParser.php | 101 + .../yiisoft/yii/docs/viewer/config/main.php | 11 + .../viewer/controllers/BlogController.php | 134 + .../viewer/controllers/GuideController.php | 134 + .../yii/docs/viewer/runtime/.gitignore | 2 + .../yii/docs/viewer/views/blog/view.php | 43 + .../yii/docs/viewer/views/guide/view.php | 44 + .../yii/docs/viewer/views/layouts/main.php | 25 + .../vendor/yiisoft/yii/framework/.htaccess | 1 + .../vendor/yiisoft/yii/framework/YiiBase.php | 861 + .../yii/framework/base/CApplication.php | 979 + .../framework/base/CApplicationComponent.php | 57 + .../yiisoft/yii/framework/base/CBehavior.php | 114 + .../yiisoft/yii/framework/base/CComponent.php | 689 + .../yii/framework/base/CErrorEvent.php | 53 + .../yii/framework/base/CErrorHandler.php | 578 + .../yiisoft/yii/framework/base/CException.php | 21 + .../yii/framework/base/CExceptionEvent.php | 35 + .../yii/framework/base/CHttpException.php | 39 + .../yiisoft/yii/framework/base/CModel.php | 635 + .../yii/framework/base/CModelBehavior.php | 68 + .../yii/framework/base/CModelEvent.php | 31 + .../yiisoft/yii/framework/base/CModule.php | 547 + .../yii/framework/base/CSecurityManager.php | 344 + .../yii/framework/base/CStatePersister.php | 107 + .../yiisoft/yii/framework/base/interfaces.php | 631 + .../yii/framework/caching/CApcCache.php | 108 + .../yiisoft/yii/framework/caching/CCache.php | 376 + .../yii/framework/caching/CDbCache.php | 313 + .../yii/framework/caching/CDummyCache.php | 163 + .../framework/caching/CEAcceleratorCache.php | 106 + .../yii/framework/caching/CFileCache.php | 242 + .../yii/framework/caching/CMemCache.php | 281 + .../yii/framework/caching/CRedisCache.php | 250 + .../yii/framework/caching/CWinCache.php | 108 + .../yiisoft/yii/framework/caching/CXCache.php | 103 + .../yii/framework/caching/CZendDataCache.php | 98 + .../caching/dependencies/CCacheDependency.php | 117 + .../dependencies/CChainedCacheDependency.php | 97 + .../dependencies/CDbCacheDependency.php | 112 + .../CDirectoryCacheDependency.php | 135 + .../dependencies/CExpressionDependency.php | 55 + .../dependencies/CFileCacheDependency.php | 53 + .../CGlobalStateCacheDependency.php | 54 + .../framework/cli/commands/MessageCommand.php | 228 + .../framework/cli/commands/MigrateCommand.php | 585 + .../framework/cli/commands/ShellCommand.php | 146 + .../framework/cli/commands/WebAppCommand.php | 213 + .../cli/commands/shell/ControllerCommand.php | 175 + .../cli/commands/shell/CrudCommand.php | 326 + .../cli/commands/shell/FormCommand.php | 122 + .../cli/commands/shell/HelpCommand.php | 78 + .../cli/commands/shell/ModelCommand.php | 488 + .../cli/commands/shell/ModuleCommand.php | 93 + .../yii/framework/cli/runtime/.gitignore | 1 + .../cli/views/shell/controller/controller.php | 47 + .../cli/views/shell/controller/view.php | 26 + .../framework/cli/views/shell/crud/_form.php | 42 + .../cli/views/shell/crud/_search.php | 35 + .../framework/cli/views/shell/crud/_view.php | 29 + .../framework/cli/views/shell/crud/admin.php | 73 + .../cli/views/shell/crud/controller.php | 190 + .../framework/cli/views/shell/crud/create.php | 27 + .../framework/cli/views/shell/crud/index.php | 31 + .../framework/cli/views/shell/crud/test.php | 47 + .../framework/cli/views/shell/crud/update.php | 31 + .../framework/cli/views/shell/crud/view.php | 39 + .../framework/cli/views/shell/form/action.php | 37 + .../framework/cli/views/shell/form/form.php | 39 + .../cli/views/shell/model/fixture.php | 25 + .../framework/cli/views/shell/model/model.php | 120 + .../framework/cli/views/shell/model/test.php | 21 + .../views/shell/module/components/.gitignore | 1 + .../module/controllers/DefaultController.php | 9 + .../views/shell/module/messages/.gitignore | 1 + .../cli/views/shell/module/models/.gitignore | 1 + .../cli/views/shell/module/module.php | 28 + .../shell/module/views/default/index.php | 14 + .../shell/module/views/layouts/.gitignore | 1 + .../cli/views/webapp/assets/.gitignore | 1 + .../cli/views/webapp/assets/git-gitignore | 2 + .../cli/views/webapp/assets/hg-hgkeep | 0 .../yii/framework/cli/views/webapp/css/bg.gif | Bin 0 -> 243 bytes .../framework/cli/views/webapp/css/form.css | 164 + .../yii/framework/cli/views/webapp/css/ie.css | 36 + .../framework/cli/views/webapp/css/main.css | 229 + .../framework/cli/views/webapp/css/print.css | 29 + .../framework/cli/views/webapp/css/screen.css | 238 + .../framework/cli/views/webapp/hg-hgignore | 7 + .../cli/views/webapp/images/.gitignore | 1 + .../cli/views/webapp/images/git-gitkeep | 0 .../cli/views/webapp/images/hg-hgkeep | 0 .../framework/cli/views/webapp/index-test.php | 15 + .../yii/framework/cli/views/webapp/index.php | 13 + .../cli/views/webapp/protected/.htaccess | 1 + .../protected/commands/shell/.gitignore | 1 + .../protected/commands/shell/git-gitkeep | 0 .../webapp/protected/commands/shell/hg-hgkeep | 0 .../protected/components/Controller.php | 23 + .../protected/components/UserIdentity.php | 33 + .../views/webapp/protected/config/console.php | 37 + .../views/webapp/protected/config/main.php | 90 + .../views/webapp/protected/config/test.php | 17 + .../protected/controllers/SiteController.php | 109 + .../webapp/protected/data/schema.mysql.sql | 28 + .../webapp/protected/data/schema.sqlite.sql | 28 + .../views/webapp/protected/data/testdrive.db | Bin 0 -> 3072 bytes .../webapp/protected/extensions/.gitignore | 1 + .../webapp/protected/extensions/git-gitkeep | 0 .../webapp/protected/extensions/hg-hgkeep | 0 .../webapp/protected/messages/.gitignore | 1 + .../webapp/protected/messages/git-gitkeep | 0 .../views/webapp/protected/messages/hg-hgkeep | 0 .../webapp/protected/migrations/.gitignore | 1 + .../webapp/protected/migrations/git-gitkeep | 0 .../webapp/protected/migrations/hg-hgkeep | 0 .../webapp/protected/models/ContactForm.php | 42 + .../webapp/protected/models/LoginForm.php | 77 + .../views/webapp/protected/runtime/.gitignore | 1 + .../webapp/protected/runtime/git-gitignore | 2 + .../views/webapp/protected/runtime/hg-hgkeep | 0 .../webapp/protected/tests/WebTestCase.php | 25 + .../webapp/protected/tests/bootstrap.php | 10 + .../protected/tests/fixtures/.gitignore | 1 + .../protected/tests/fixtures/git-gitkeep | 0 .../webapp/protected/tests/fixtures/hg-hgkeep | 0 .../protected/tests/functional/SiteTest.php | 47 + .../views/webapp/protected/tests/phpunit.xml | 13 + .../webapp/protected/tests/report/.gitignore | 1 + .../protected/tests/report/git-gitignore | 2 + .../webapp/protected/tests/report/hg-hgkeep | 0 .../webapp/protected/tests/unit/.gitignore | 1 + .../webapp/protected/tests/unit/git-gitkeep | 0 .../webapp/protected/tests/unit/hg-hgkeep | 0 .../views/webapp/protected/vendor/.gitignore | 1 + .../views/webapp/protected/vendor/git-gitkeep | 0 .../views/webapp/protected/vendor/hg-hgkeep | 0 .../protected/views/layouts/column1.php | 6 + .../protected/views/layouts/column2.php | 22 + .../webapp/protected/views/layouts/main.php | 59 + .../webapp/protected/views/site/contact.php | 85 + .../webapp/protected/views/site/error.php | 15 + .../webapp/protected/views/site/index.php | 20 + .../webapp/protected/views/site/login.php | 53 + .../protected/views/site/pages/about.php | 12 + .../framework/cli/views/webapp/protected/yiic | 4 + .../cli/views/webapp/protected/yiic.bat | 16 + .../cli/views/webapp/protected/yiic.php | 7 + .../webapp/themes/classic/views/.htaccess | 1 + .../themes/classic/views/layouts/.gitignore | 1 + .../themes/classic/views/layouts/git-gitkeep | 0 .../themes/classic/views/layouts/hg-hgkeep | 0 .../themes/classic/views/site/.gitignore | 1 + .../themes/classic/views/site/git-gitkeep | 0 .../themes/classic/views/site/hg-hgkeep | 0 .../themes/classic/views/system/.gitignore | 1 + .../themes/classic/views/system/git-gitkeep | 0 .../themes/classic/views/system/hg-hgkeep | 0 .../collections/CAttributeCollection.php | 213 + .../framework/collections/CConfiguration.php | 100 + .../yii/framework/collections/CList.php | 345 + .../framework/collections/CListIterator.php | 93 + .../yii/framework/collections/CMap.php | 342 + .../framework/collections/CMapIterator.php | 93 + .../yii/framework/collections/CQueue.php | 171 + .../framework/collections/CQueueIterator.php | 93 + .../yii/framework/collections/CStack.php | 172 + .../framework/collections/CStackIterator.php | 93 + .../yii/framework/collections/CTypedList.php | 51 + .../yii/framework/collections/CTypedMap.php | 51 + .../framework/console/CConsoleApplication.php | 200 + .../yii/framework/console/CConsoleCommand.php | 599 + .../console/CConsoleCommandBehavior.php | 53 + .../console/CConsoleCommandEvent.php | 52 + .../console/CConsoleCommandRunner.php | 180 + .../yii/framework/console/CHelpCommand.php | 76 + .../yiisoft/yii/framework/db/CDbCommand.php | 1610 ++ .../yii/framework/db/CDbConnection.php | 823 + .../yii/framework/db/CDbDataReader.php | 245 + .../yiisoft/yii/framework/db/CDbException.php | 38 + .../yiisoft/yii/framework/db/CDbMigration.php | 431 + .../yii/framework/db/CDbTransaction.php | 110 + .../yii/framework/db/ar/CActiveFinder.php | 1638 ++ .../yii/framework/db/ar/CActiveRecord.php | 2436 +++ .../framework/db/ar/CActiveRecordBehavior.php | 114 + .../framework/db/schema/CDbColumnSchema.php | 153 + .../framework/db/schema/CDbCommandBuilder.php | 873 + .../yii/framework/db/schema/CDbCriteria.php | 644 + .../yii/framework/db/schema/CDbExpression.php | 60 + .../yii/framework/db/schema/CDbSchema.php | 597 + .../framework/db/schema/CDbTableSchema.php | 77 + .../db/schema/mssql/CMssqlColumnSchema.php | 88 + .../db/schema/mssql/CMssqlCommandBuilder.php | 338 + .../db/schema/mssql/CMssqlPdoAdapter.php | 72 + .../db/schema/mssql/CMssqlSchema.php | 439 + .../schema/mssql/CMssqlSqlsrvPdoAdapter.php | 36 + .../db/schema/mssql/CMssqlTableSchema.php | 31 + .../db/schema/mysql/CMysqlColumnSchema.php | 74 + .../db/schema/mysql/CMysqlCommandBuilder.php | 43 + .../db/schema/mysql/CMysqlSchema.php | 361 + .../db/schema/mysql/CMysqlTableSchema.php | 25 + .../db/schema/oci/COciColumnSchema.php | 65 + .../db/schema/oci/COciCommandBuilder.php | 147 + .../framework/db/schema/oci/COciSchema.php | 411 + .../db/schema/oci/COciTableSchema.php | 24 + .../db/schema/pgsql/CPgsqlColumnSchema.php | 57 + .../db/schema/pgsql/CPgsqlCommandBuilder.php | 30 + .../db/schema/pgsql/CPgsqlSchema.php | 437 + .../db/schema/pgsql/CPgsqlTableSchema.php | 24 + .../db/schema/sqlite/CSqliteColumnSchema.php | 35 + .../schema/sqlite/CSqliteCommandBuilder.php | 63 + .../db/schema/sqlite/CSqliteSchema.php | 333 + .../yiisoft/yii/framework/gii/CCodeFile.php | 134 + .../yiisoft/yii/framework/gii/CCodeForm.php | 59 + .../yii/framework/gii/CCodeGenerator.php | 167 + .../yiisoft/yii/framework/gii/CCodeModel.php | 484 + .../yiisoft/yii/framework/gii/GiiModule.php | 244 + .../yii/framework/gii/assets/css/ie.css | 35 + .../yii/framework/gii/assets/css/main.css | 528 + .../yii/framework/gii/assets/css/print.css | 29 + .../yii/framework/gii/assets/css/screen.css | 235 + .../yii/framework/gii/assets/images/logo.png | Bin 0 -> 7207 bytes .../gii/assets/js/fancybox/blank.gif | Bin 0 -> 43 bytes .../gii/assets/js/fancybox/fancy_close.png | Bin 0 -> 1075 bytes .../gii/assets/js/fancybox/fancy_loading.png | Bin 0 -> 8132 bytes .../gii/assets/js/fancybox/fancy_nav_left.png | Bin 0 -> 1029 bytes .../assets/js/fancybox/fancy_nav_right.png | Bin 0 -> 1034 bytes .../gii/assets/js/fancybox/fancy_shadow_e.png | Bin 0 -> 107 bytes .../gii/assets/js/fancybox/fancy_shadow_n.png | Bin 0 -> 101 bytes .../assets/js/fancybox/fancy_shadow_ne.png | Bin 0 -> 313 bytes .../assets/js/fancybox/fancy_shadow_nw.png | Bin 0 -> 310 bytes .../gii/assets/js/fancybox/fancy_shadow_s.png | Bin 0 -> 107 bytes .../assets/js/fancybox/fancy_shadow_se.png | Bin 0 -> 330 bytes .../assets/js/fancybox/fancy_shadow_sw.png | Bin 0 -> 317 bytes .../gii/assets/js/fancybox/fancy_shadow_w.png | Bin 0 -> 99 bytes .../assets/js/fancybox/fancy_title_left.png | Bin 0 -> 496 bytes .../assets/js/fancybox/fancy_title_main.png | Bin 0 -> 96 bytes .../assets/js/fancybox/fancy_title_over.png | Bin 0 -> 68 bytes .../assets/js/fancybox/fancy_title_right.png | Bin 0 -> 495 bytes .../gii/assets/js/fancybox/fancybox-x.png | Bin 0 -> 159 bytes .../gii/assets/js/fancybox/fancybox-y.png | Bin 0 -> 128 bytes .../gii/assets/js/fancybox/fancybox.png | Bin 0 -> 14353 bytes .../js/fancybox/jquery.fancybox-1.3.1.css | 363 + .../js/fancybox/jquery.fancybox-1.3.1.pack.js | 44 + .../yii/framework/gii/assets/js/main.js | 79 + .../yii/framework/gii/assets/js/tooltip.js | 364 + .../gii/components/Pear/Text/Diff.php | 453 + .../Pear/Text/Diff/Engine/native.php | 438 + .../Pear/Text/Diff/Engine/shell.php | 162 + .../Pear/Text/Diff/Engine/string.php | 237 + .../Pear/Text/Diff/Engine/xdiff.php | 63 + .../gii/components/Pear/Text/Diff/Mapped.php | 55 + .../components/Pear/Text/Diff/Renderer.php | 237 + .../Pear/Text/Diff/Renderer/context.php | 77 + .../Pear/Text/Diff/Renderer/inline.php | 170 + .../Pear/Text/Diff/Renderer/unified.php | 67 + .../components/Pear/Text/Diff/ThreeWay.php | 276 + .../gii/components/Pear/Text/Diff3.php | 276 + .../yii/framework/gii/components/TextDiff.php | 22 + .../framework/gii/components/UserIdentity.php | 20 + .../gii/controllers/DefaultController.php | 58 + .../generators/controller/ControllerCode.php | 130 + .../controller/ControllerGenerator.php | 6 + .../templates/default/controller.php | 45 + .../controller/templates/default/view.php | 36 + .../gii/generators/controller/views/index.php | 45 + .../gii/generators/crud/CrudCode.php | 248 + .../gii/generators/crud/CrudGenerator.php | 6 + .../crud/templates/default/_form.php | 49 + .../crud/templates/default/_search.php | 38 + .../crud/templates/default/_view.php | 31 + .../crud/templates/default/admin.php | 73 + .../crud/templates/default/controller.php | 180 + .../crud/templates/default/create.php | 27 + .../crud/templates/default/index.php | 29 + .../crud/templates/default/update.php | 31 + .../crud/templates/default/view.php | 39 + .../gii/generators/crud/views/index.php | 64 + .../gii/generators/form/FormCode.php | 94 + .../gii/generators/form/FormGenerator.php | 6 + .../form/templates/default/action.php | 33 + .../form/templates/default/form.php | 44 + .../gii/generators/form/views/index.php | 49 + .../gii/generators/model/ModelCode.php | 430 + .../gii/generators/model/ModelGenerator.php | 25 + .../model/templates/default/model.php | 163 + .../gii/generators/model/views/index.php | 149 + .../gii/generators/module/ModuleCode.php | 94 + .../gii/generators/module/ModuleGenerator.php | 6 + .../templates/default/components/.gitignore | 1 + .../default/controllers/DefaultController.php | 9 + .../templates/default/messages/.gitignore | 1 + .../templates/default/models/.gitignore | 1 + .../module/templates/default/module.php | 28 + .../templates/default/views/default/index.php | 17 + .../default/views/layouts/.gitignore | 1 + .../gii/generators/module/views/index.php | 19 + .../yii/framework/gii/models/LoginForm.php | 49 + .../yii/framework/gii/views/common/code.php | 16 + .../yii/framework/gii/views/common/diff.php | 9 + .../framework/gii/views/common/generator.php | 76 + .../yii/framework/gii/views/default/error.php | 5 + .../yii/framework/gii/views/default/index.php | 11 + .../yii/framework/gii/views/default/login.php | 11 + .../framework/gii/views/layouts/column1.php | 7 + .../framework/gii/views/layouts/generator.php | 25 + .../yii/framework/gii/views/layouts/main.php | 57 + .../yii/framework/i18n/CChoiceFormat.php | 76 + .../yii/framework/i18n/CDateFormatter.php | 559 + .../yii/framework/i18n/CDbMessageSource.php | 138 + .../framework/i18n/CGettextMessageSource.php | 116 + .../yiisoft/yii/framework/i18n/CLocale.php | 472 + .../yii/framework/i18n/CMessageSource.php | 166 + .../yii/framework/i18n/CNumberFormatter.php | 295 + .../yii/framework/i18n/CPhpMessageSource.php | 160 + .../yii/framework/i18n/data/README.txt | 10 + .../yiisoft/yii/framework/i18n/data/aa.php | 215 + .../yiisoft/yii/framework/i18n/data/aa_dj.php | 216 + .../yiisoft/yii/framework/i18n/data/aa_er.php | 216 + .../yiisoft/yii/framework/i18n/data/aa_et.php | 215 + .../yiisoft/yii/framework/i18n/data/af.php | 726 + .../yiisoft/yii/framework/i18n/data/af_na.php | 727 + .../yiisoft/yii/framework/i18n/data/af_za.php | 726 + .../yiisoft/yii/framework/i18n/data/agq.php | 456 + .../yii/framework/i18n/data/agq_cm.php | 456 + .../yiisoft/yii/framework/i18n/data/ak.php | 460 + .../yiisoft/yii/framework/i18n/data/ak_gh.php | 460 + .../yiisoft/yii/framework/i18n/data/am.php | 726 + .../yiisoft/yii/framework/i18n/data/am_et.php | 726 + .../yiisoft/yii/framework/i18n/data/ar.php | 1131 + .../yii/framework/i18n/data/ar_001.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_ae.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_bh.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_dz.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_eg.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_iq.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_jo.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_kw.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_lb.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_ly.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_ma.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_om.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_qa.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_sa.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_sd.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_sy.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_tn.php | 1131 + .../yiisoft/yii/framework/i18n/data/ar_ye.php | 1131 + .../yiisoft/yii/framework/i18n/data/as.php | 209 + .../yiisoft/yii/framework/i18n/data/as_in.php | 209 + .../yiisoft/yii/framework/i18n/data/asa.php | 460 + .../yii/framework/i18n/data/asa_tz.php | 460 + .../yiisoft/yii/framework/i18n/data/az.php | 1089 + .../yii/framework/i18n/data/az_arab.php | 321 + .../yii/framework/i18n/data/az_arab_ir.php | 321 + .../yiisoft/yii/framework/i18n/data/az_az.php | 321 + .../yii/framework/i18n/data/az_cyrl.php | 1089 + .../yii/framework/i18n/data/az_cyrl_az.php | 1089 + .../yiisoft/yii/framework/i18n/data/az_ir.php | 321 + .../yii/framework/i18n/data/az_latn.php | 1089 + .../yii/framework/i18n/data/az_latn_az.php | 1089 + .../yiisoft/yii/framework/i18n/data/bas.php | 453 + .../yii/framework/i18n/data/bas_cm.php | 453 + .../yiisoft/yii/framework/i18n/data/be.php | 661 + .../yiisoft/yii/framework/i18n/data/be_by.php | 661 + .../yiisoft/yii/framework/i18n/data/bem.php | 237 + .../yii/framework/i18n/data/bem_zm.php | 237 + .../yiisoft/yii/framework/i18n/data/bez.php | 462 + .../yii/framework/i18n/data/bez_tz.php | 462 + .../yiisoft/yii/framework/i18n/data/bg.php | 1109 + .../yiisoft/yii/framework/i18n/data/bg_bg.php | 1109 + .../yiisoft/yii/framework/i18n/data/bm.php | 456 + .../yiisoft/yii/framework/i18n/data/bm_ml.php | 456 + .../yiisoft/yii/framework/i18n/data/bn.php | 1118 + .../yiisoft/yii/framework/i18n/data/bn_bd.php | 1118 + .../yiisoft/yii/framework/i18n/data/bn_in.php | 1118 + .../yiisoft/yii/framework/i18n/data/bo.php | 454 + .../yiisoft/yii/framework/i18n/data/bo_cn.php | 454 + .../yiisoft/yii/framework/i18n/data/bo_in.php | 454 + .../yiisoft/yii/framework/i18n/data/br.php | 752 + .../yiisoft/yii/framework/i18n/data/br_fr.php | 752 + .../yiisoft/yii/framework/i18n/data/brx.php | 1096 + .../yii/framework/i18n/data/brx_in.php | 1096 + .../yiisoft/yii/framework/i18n/data/bs.php | 1110 + .../yiisoft/yii/framework/i18n/data/bs_ba.php | 1110 + .../yiisoft/yii/framework/i18n/data/byn.php | 462 + .../yii/framework/i18n/data/byn_er.php | 462 + .../yiisoft/yii/framework/i18n/data/ca.php | 1193 ++ .../yiisoft/yii/framework/i18n/data/ca_es.php | 1193 ++ .../yiisoft/yii/framework/i18n/data/cch.php | 180 + .../yii/framework/i18n/data/cch_ng.php | 180 + .../yiisoft/yii/framework/i18n/data/cgg.php | 460 + .../yii/framework/i18n/data/cgg_ug.php | 460 + .../yiisoft/yii/framework/i18n/data/chr.php | 417 + .../yii/framework/i18n/data/chr_us.php | 417 + .../yiisoft/yii/framework/i18n/data/cs.php | 1123 + .../yiisoft/yii/framework/i18n/data/cs_cz.php | 1123 + .../yiisoft/yii/framework/i18n/data/cy.php | 620 + .../yiisoft/yii/framework/i18n/data/cy_gb.php | 620 + .../yiisoft/yii/framework/i18n/data/da.php | 1137 + .../yiisoft/yii/framework/i18n/data/da_dk.php | 1137 + .../yiisoft/yii/framework/i18n/data/dav.php | 457 + .../yii/framework/i18n/data/dav_ke.php | 457 + .../yiisoft/yii/framework/i18n/data/de.php | 1141 + .../yiisoft/yii/framework/i18n/data/de_at.php | 1141 + .../yiisoft/yii/framework/i18n/data/de_be.php | 1141 + .../yiisoft/yii/framework/i18n/data/de_ch.php | 1141 + .../yiisoft/yii/framework/i18n/data/de_de.php | 1141 + .../yiisoft/yii/framework/i18n/data/de_li.php | 1141 + .../yiisoft/yii/framework/i18n/data/de_lu.php | 1142 + .../yiisoft/yii/framework/i18n/data/dje.php | 455 + .../yii/framework/i18n/data/dje_ne.php | 455 + .../yiisoft/yii/framework/i18n/data/dua.php | 187 + .../yii/framework/i18n/data/dua_cm.php | 187 + .../yiisoft/yii/framework/i18n/data/dv.php | 322 + .../yiisoft/yii/framework/i18n/data/dv_mv.php | 322 + .../yiisoft/yii/framework/i18n/data/dyo.php | 338 + .../yii/framework/i18n/data/dyo_sn.php | 338 + .../yiisoft/yii/framework/i18n/data/dz.php | 340 + .../yiisoft/yii/framework/i18n/data/dz_bt.php | 340 + .../yiisoft/yii/framework/i18n/data/ebu.php | 457 + .../yii/framework/i18n/data/ebu_ke.php | 457 + .../yiisoft/yii/framework/i18n/data/ee.php | 781 + .../yiisoft/yii/framework/i18n/data/ee_gh.php | 781 + .../yiisoft/yii/framework/i18n/data/ee_tg.php | 781 + .../yiisoft/yii/framework/i18n/data/el.php | 1203 ++ .../yiisoft/yii/framework/i18n/data/el_cy.php | 1203 ++ .../yiisoft/yii/framework/i18n/data/el_gr.php | 1203 ++ .../yii/framework/i18n/data/el_polyton.php | 1203 ++ .../yiisoft/yii/framework/i18n/data/en.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_as.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_au.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_bb.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_be.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_bm.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_bw.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_bz.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_ca.php | 1197 ++ .../yii/framework/i18n/data/en_dsrt.php | 1240 ++ .../yii/framework/i18n/data/en_dsrt_us.php | 1240 ++ .../yiisoft/yii/framework/i18n/data/en_gb.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_gu.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_gy.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_hk.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_ie.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_in.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_jm.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_mh.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_mp.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_mt.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_mu.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_na.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_nz.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_ph.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_pk.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_sg.php | 1198 ++ .../yii/framework/i18n/data/en_shaw.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_tt.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_um.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_us.php | 1197 ++ .../yii/framework/i18n/data/en_us_posix.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_vi.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_za.php | 1198 ++ .../yiisoft/yii/framework/i18n/data/en_zw.php | 1197 ++ .../yiisoft/yii/framework/i18n/data/en_zz.php | 326 + .../yiisoft/yii/framework/i18n/data/eo.php | 570 + .../yiisoft/yii/framework/i18n/data/es.php | 1118 + .../yii/framework/i18n/data/es_419.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_ar.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_bo.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_cl.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_co.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_cr.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_do.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_ec.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_es.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_gq.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_gt.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_hn.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_mx.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_ni.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_pa.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_pe.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_pr.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_py.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_sv.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_us.php | 1118 + .../yiisoft/yii/framework/i18n/data/es_uy.php | 1119 + .../yiisoft/yii/framework/i18n/data/es_ve.php | 1119 + .../yiisoft/yii/framework/i18n/data/et.php | 1082 + .../yiisoft/yii/framework/i18n/data/et_ee.php | 1082 + .../yiisoft/yii/framework/i18n/data/eu.php | 684 + .../yiisoft/yii/framework/i18n/data/eu_es.php | 684 + .../yiisoft/yii/framework/i18n/data/ewo.php | 456 + .../yii/framework/i18n/data/ewo_cm.php | 456 + .../yiisoft/yii/framework/i18n/data/fa.php | 1146 + .../yiisoft/yii/framework/i18n/data/fa_af.php | 1147 + .../yiisoft/yii/framework/i18n/data/fa_ir.php | 1146 + .../yiisoft/yii/framework/i18n/data/ff.php | 461 + .../yiisoft/yii/framework/i18n/data/ff_sn.php | 461 + .../yiisoft/yii/framework/i18n/data/fi.php | 1201 ++ .../yiisoft/yii/framework/i18n/data/fi_fi.php | 1201 ++ .../yiisoft/yii/framework/i18n/data/fil.php | 690 + .../yii/framework/i18n/data/fil_ph.php | 690 + .../yiisoft/yii/framework/i18n/data/fo.php | 625 + .../yiisoft/yii/framework/i18n/data/fo_fo.php | 625 + .../yiisoft/yii/framework/i18n/data/fr.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_be.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_bf.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_bi.php | 1216 ++ .../yiisoft/yii/framework/i18n/data/fr_bj.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_bl.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_ca.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_cd.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_cf.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_cg.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_ch.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_ci.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_cm.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_dj.php | 1216 ++ .../yiisoft/yii/framework/i18n/data/fr_fr.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_ga.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_gf.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_gn.php | 1216 ++ .../yiisoft/yii/framework/i18n/data/fr_gp.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_gq.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_km.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_lu.php | 1216 ++ .../yiisoft/yii/framework/i18n/data/fr_mc.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_mf.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_mg.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_ml.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_mq.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_ne.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_re.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_rw.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_sn.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_td.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_tg.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fr_yt.php | 1215 ++ .../yiisoft/yii/framework/i18n/data/fur.php | 809 + .../yii/framework/i18n/data/fur_it.php | 809 + .../yiisoft/yii/framework/i18n/data/ga.php | 638 + .../yiisoft/yii/framework/i18n/data/ga_ie.php | 638 + .../yiisoft/yii/framework/i18n/data/gaa.php | 179 + .../yii/framework/i18n/data/gaa_gh.php | 179 + .../yiisoft/yii/framework/i18n/data/gd.php | 708 + .../yiisoft/yii/framework/i18n/data/gd_gb.php | 708 + .../yiisoft/yii/framework/i18n/data/gez.php | 321 + .../yii/framework/i18n/data/gez_er.php | 321 + .../yii/framework/i18n/data/gez_et.php | 321 + .../yiisoft/yii/framework/i18n/data/gl.php | 714 + .../yiisoft/yii/framework/i18n/data/gl_es.php | 714 + .../yiisoft/yii/framework/i18n/data/gsw.php | 1114 + .../yii/framework/i18n/data/gsw_ch.php | 1114 + .../yiisoft/yii/framework/i18n/data/gu.php | 1116 + .../yiisoft/yii/framework/i18n/data/gu_in.php | 1116 + .../yiisoft/yii/framework/i18n/data/guz.php | 457 + .../yii/framework/i18n/data/guz_ke.php | 457 + .../yiisoft/yii/framework/i18n/data/gv.php | 192 + .../yiisoft/yii/framework/i18n/data/gv_gb.php | 192 + .../yiisoft/yii/framework/i18n/data/ha.php | 528 + .../yii/framework/i18n/data/ha_arab.php | 326 + .../yii/framework/i18n/data/ha_arab_ng.php | 326 + .../yii/framework/i18n/data/ha_arab_sd.php | 326 + .../yiisoft/yii/framework/i18n/data/ha_gh.php | 326 + .../yii/framework/i18n/data/ha_latn.php | 528 + .../yii/framework/i18n/data/ha_latn_gh.php | 528 + .../yii/framework/i18n/data/ha_latn_ne.php | 528 + .../yii/framework/i18n/data/ha_latn_ng.php | 528 + .../yiisoft/yii/framework/i18n/data/ha_ne.php | 326 + .../yiisoft/yii/framework/i18n/data/ha_ng.php | 326 + .../yiisoft/yii/framework/i18n/data/ha_sd.php | 326 + .../yiisoft/yii/framework/i18n/data/haw.php | 247 + .../yii/framework/i18n/data/haw_us.php | 247 + .../yiisoft/yii/framework/i18n/data/he.php | 857 + .../yiisoft/yii/framework/i18n/data/he_il.php | 857 + .../yiisoft/yii/framework/i18n/data/hi.php | 1117 + .../yiisoft/yii/framework/i18n/data/hi_in.php | 1117 + .../yiisoft/yii/framework/i18n/data/hr.php | 1195 ++ .../yiisoft/yii/framework/i18n/data/hr_hr.php | 1195 ++ .../yiisoft/yii/framework/i18n/data/hu.php | 1196 ++ .../yiisoft/yii/framework/i18n/data/hu_hu.php | 1196 ++ .../yiisoft/yii/framework/i18n/data/hy.php | 489 + .../yiisoft/yii/framework/i18n/data/hy_am.php | 489 + .../yiisoft/yii/framework/i18n/data/ia.php | 468 + .../yiisoft/yii/framework/i18n/data/id.php | 1100 + .../yiisoft/yii/framework/i18n/data/id_id.php | 1100 + .../yiisoft/yii/framework/i18n/data/ig.php | 238 + .../yiisoft/yii/framework/i18n/data/ig_ng.php | 238 + .../yiisoft/yii/framework/i18n/data/ii.php | 221 + .../yiisoft/yii/framework/i18n/data/ii_cn.php | 221 + .../yiisoft/yii/framework/i18n/data/in.php | 321 + .../yiisoft/yii/framework/i18n/data/is.php | 1108 + .../yiisoft/yii/framework/i18n/data/is_is.php | 1108 + .../yiisoft/yii/framework/i18n/data/it.php | 1158 + .../yiisoft/yii/framework/i18n/data/it_ch.php | 1158 + .../yiisoft/yii/framework/i18n/data/it_it.php | 1158 + .../yiisoft/yii/framework/i18n/data/iu.php | 321 + .../yiisoft/yii/framework/i18n/data/iw.php | 326 + .../yiisoft/yii/framework/i18n/data/ja.php | 1098 + .../yiisoft/yii/framework/i18n/data/ja_jp.php | 1098 + .../yiisoft/yii/framework/i18n/data/jmc.php | 462 + .../yii/framework/i18n/data/jmc_tz.php | 462 + .../yiisoft/yii/framework/i18n/data/ka.php | 668 + .../yiisoft/yii/framework/i18n/data/ka_ge.php | 668 + .../yiisoft/yii/framework/i18n/data/kab.php | 462 + .../yii/framework/i18n/data/kab_dz.php | 462 + .../yiisoft/yii/framework/i18n/data/kaj.php | 185 + .../yii/framework/i18n/data/kaj_ng.php | 185 + .../yiisoft/yii/framework/i18n/data/kam.php | 457 + .../yii/framework/i18n/data/kam_ke.php | 457 + .../yiisoft/yii/framework/i18n/data/kcg.php | 185 + .../yii/framework/i18n/data/kcg_ng.php | 185 + .../yiisoft/yii/framework/i18n/data/kde.php | 457 + .../yii/framework/i18n/data/kde_tz.php | 457 + .../yiisoft/yii/framework/i18n/data/kea.php | 599 + .../yii/framework/i18n/data/kea_cv.php | 599 + .../yiisoft/yii/framework/i18n/data/kfo.php | 321 + .../yii/framework/i18n/data/kfo_ci.php | 321 + .../yiisoft/yii/framework/i18n/data/khq.php | 456 + .../yii/framework/i18n/data/khq_ml.php | 456 + .../yiisoft/yii/framework/i18n/data/ki.php | 457 + .../yiisoft/yii/framework/i18n/data/ki_ke.php | 457 + .../yiisoft/yii/framework/i18n/data/kk.php | 504 + .../yii/framework/i18n/data/kk_cyrl.php | 504 + .../yii/framework/i18n/data/kk_cyrl_kz.php | 504 + .../yiisoft/yii/framework/i18n/data/kk_kz.php | 322 + .../yiisoft/yii/framework/i18n/data/kl.php | 452 + .../yiisoft/yii/framework/i18n/data/kl_gl.php | 452 + .../yiisoft/yii/framework/i18n/data/kln.php | 457 + .../yii/framework/i18n/data/kln_ke.php | 457 + .../yiisoft/yii/framework/i18n/data/km.php | 485 + .../yiisoft/yii/framework/i18n/data/km_kh.php | 485 + .../yiisoft/yii/framework/i18n/data/kn.php | 1112 + .../yiisoft/yii/framework/i18n/data/kn_in.php | 1112 + .../yiisoft/yii/framework/i18n/data/ko.php | 1094 + .../yiisoft/yii/framework/i18n/data/ko_kr.php | 1094 + .../yiisoft/yii/framework/i18n/data/kok.php | 326 + .../yii/framework/i18n/data/kok_in.php | 326 + .../yiisoft/yii/framework/i18n/data/kpe.php | 321 + .../yii/framework/i18n/data/kpe_gn.php | 321 + .../yii/framework/i18n/data/kpe_lr.php | 321 + .../yiisoft/yii/framework/i18n/data/ksb.php | 461 + .../yii/framework/i18n/data/ksb_tz.php | 461 + .../yiisoft/yii/framework/i18n/data/ksf.php | 456 + .../yii/framework/i18n/data/ksf_cm.php | 456 + .../yiisoft/yii/framework/i18n/data/ksh.php | 685 + .../yii/framework/i18n/data/ksh_de.php | 685 + .../yiisoft/yii/framework/i18n/data/ku.php | 624 + .../yii/framework/i18n/data/ku_arab.php | 624 + .../yii/framework/i18n/data/ku_arab_iq.php | 624 + .../yii/framework/i18n/data/ku_arab_ir.php | 624 + .../yiisoft/yii/framework/i18n/data/ku_iq.php | 319 + .../yiisoft/yii/framework/i18n/data/ku_ir.php | 319 + .../yii/framework/i18n/data/ku_latn.php | 626 + .../yii/framework/i18n/data/ku_latn_sy.php | 626 + .../yii/framework/i18n/data/ku_latn_tr.php | 626 + .../yiisoft/yii/framework/i18n/data/ku_sy.php | 319 + .../yiisoft/yii/framework/i18n/data/ku_tr.php | 319 + .../yiisoft/yii/framework/i18n/data/kw.php | 225 + .../yiisoft/yii/framework/i18n/data/kw_gb.php | 225 + .../yiisoft/yii/framework/i18n/data/ky.php | 267 + .../yiisoft/yii/framework/i18n/data/ky_kg.php | 267 + .../yiisoft/yii/framework/i18n/data/lag.php | 463 + .../yii/framework/i18n/data/lag_tz.php | 463 + .../yiisoft/yii/framework/i18n/data/lg.php | 462 + .../yiisoft/yii/framework/i18n/data/lg_ug.php | 462 + .../yiisoft/yii/framework/i18n/data/ln.php | 460 + .../yiisoft/yii/framework/i18n/data/ln_cd.php | 460 + .../yiisoft/yii/framework/i18n/data/ln_cg.php | 460 + .../yiisoft/yii/framework/i18n/data/lo.php | 528 + .../yiisoft/yii/framework/i18n/data/lo_la.php | 528 + .../yiisoft/yii/framework/i18n/data/lt.php | 1192 ++ .../yiisoft/yii/framework/i18n/data/lt_lt.php | 1192 ++ .../yiisoft/yii/framework/i18n/data/lu.php | 454 + .../yiisoft/yii/framework/i18n/data/lu_cd.php | 454 + .../yiisoft/yii/framework/i18n/data/luo.php | 456 + .../yii/framework/i18n/data/luo_ke.php | 456 + .../yiisoft/yii/framework/i18n/data/luy.php | 456 + .../yii/framework/i18n/data/luy_ke.php | 456 + .../yiisoft/yii/framework/i18n/data/lv.php | 1073 + .../yiisoft/yii/framework/i18n/data/lv_lv.php | 1073 + .../yiisoft/yii/framework/i18n/data/mas.php | 462 + .../yii/framework/i18n/data/mas_ke.php | 462 + .../yii/framework/i18n/data/mas_tz.php | 463 + .../yiisoft/yii/framework/i18n/data/mer.php | 457 + .../yii/framework/i18n/data/mer_ke.php | 457 + .../yiisoft/yii/framework/i18n/data/mfe.php | 456 + .../yii/framework/i18n/data/mfe_mu.php | 456 + .../yiisoft/yii/framework/i18n/data/mg.php | 461 + .../yiisoft/yii/framework/i18n/data/mg_mg.php | 461 + .../yiisoft/yii/framework/i18n/data/mgh.php | 368 + .../yii/framework/i18n/data/mgh_mz.php | 368 + .../yiisoft/yii/framework/i18n/data/mi.php | 321 + .../yiisoft/yii/framework/i18n/data/mi_nz.php | 321 + .../yiisoft/yii/framework/i18n/data/mk.php | 1026 + .../yiisoft/yii/framework/i18n/data/mk_mk.php | 1026 + .../yiisoft/yii/framework/i18n/data/ml.php | 1117 + .../yiisoft/yii/framework/i18n/data/ml_in.php | 1117 + .../yiisoft/yii/framework/i18n/data/mn.php | 307 + .../yiisoft/yii/framework/i18n/data/mn_cn.php | 326 + .../yii/framework/i18n/data/mn_cyrl.php | 307 + .../yii/framework/i18n/data/mn_cyrl_mn.php | 307 + .../yiisoft/yii/framework/i18n/data/mn_mn.php | 326 + .../yii/framework/i18n/data/mn_mong.php | 307 + .../yii/framework/i18n/data/mn_mong_cn.php | 307 + .../yiisoft/yii/framework/i18n/data/mo.php | 327 + .../yiisoft/yii/framework/i18n/data/mr.php | 1164 + .../yiisoft/yii/framework/i18n/data/mr_in.php | 1164 + .../yiisoft/yii/framework/i18n/data/ms.php | 703 + .../yiisoft/yii/framework/i18n/data/ms_bn.php | 704 + .../yiisoft/yii/framework/i18n/data/ms_my.php | 703 + .../yiisoft/yii/framework/i18n/data/mt.php | 953 + .../yiisoft/yii/framework/i18n/data/mt_mt.php | 953 + .../yiisoft/yii/framework/i18n/data/mua.php | 456 + .../yii/framework/i18n/data/mua_cm.php | 456 + .../yiisoft/yii/framework/i18n/data/my.php | 577 + .../yiisoft/yii/framework/i18n/data/my_mm.php | 577 + .../yiisoft/yii/framework/i18n/data/naq.php | 463 + .../yii/framework/i18n/data/naq_na.php | 463 + .../yiisoft/yii/framework/i18n/data/nb.php | 1211 ++ .../yiisoft/yii/framework/i18n/data/nb_no.php | 1211 ++ .../yiisoft/yii/framework/i18n/data/nd.php | 461 + .../yiisoft/yii/framework/i18n/data/nd_zw.php | 461 + .../yiisoft/yii/framework/i18n/data/nds.php | 1100 + .../yii/framework/i18n/data/nds_de.php | 1100 + .../yiisoft/yii/framework/i18n/data/ne.php | 694 + .../yiisoft/yii/framework/i18n/data/ne_in.php | 694 + .../yiisoft/yii/framework/i18n/data/ne_np.php | 694 + .../yiisoft/yii/framework/i18n/data/nl.php | 1139 + .../yiisoft/yii/framework/i18n/data/nl_aw.php | 1140 + .../yiisoft/yii/framework/i18n/data/nl_be.php | 1139 + .../yiisoft/yii/framework/i18n/data/nl_cw.php | 1140 + .../yiisoft/yii/framework/i18n/data/nl_nl.php | 1139 + .../yiisoft/yii/framework/i18n/data/nl_sx.php | 1140 + .../yiisoft/yii/framework/i18n/data/nmg.php | 455 + .../yii/framework/i18n/data/nmg_cm.php | 455 + .../yiisoft/yii/framework/i18n/data/nn.php | 1160 + .../yiisoft/yii/framework/i18n/data/nn_no.php | 1160 + .../yiisoft/yii/framework/i18n/data/no.php | 326 + .../yiisoft/yii/framework/i18n/data/nr.php | 189 + .../yiisoft/yii/framework/i18n/data/nr_za.php | 189 + .../yiisoft/yii/framework/i18n/data/nso.php | 189 + .../yii/framework/i18n/data/nso_za.php | 189 + .../yiisoft/yii/framework/i18n/data/nus.php | 281 + .../yii/framework/i18n/data/nus_sd.php | 281 + .../yiisoft/yii/framework/i18n/data/ny.php | 321 + .../yiisoft/yii/framework/i18n/data/ny_mw.php | 321 + .../yiisoft/yii/framework/i18n/data/nyn.php | 462 + .../yii/framework/i18n/data/nyn_ug.php | 462 + .../yiisoft/yii/framework/i18n/data/oc.php | 331 + .../yiisoft/yii/framework/i18n/data/oc_fr.php | 331 + .../yiisoft/yii/framework/i18n/data/om.php | 294 + .../yiisoft/yii/framework/i18n/data/om_et.php | 294 + .../yiisoft/yii/framework/i18n/data/om_ke.php | 295 + .../yiisoft/yii/framework/i18n/data/or.php | 1109 + .../yiisoft/yii/framework/i18n/data/or_in.php | 1109 + .../yiisoft/yii/framework/i18n/data/pa.php | 261 + .../yii/framework/i18n/data/pa_arab.php | 264 + .../yii/framework/i18n/data/pa_arab_pk.php | 264 + .../yii/framework/i18n/data/pa_guru.php | 261 + .../yii/framework/i18n/data/pa_guru_in.php | 261 + .../yiisoft/yii/framework/i18n/data/pa_in.php | 326 + .../yiisoft/yii/framework/i18n/data/pa_pk.php | 326 + .../yiisoft/yii/framework/i18n/data/pl.php | 1190 ++ .../yiisoft/yii/framework/i18n/data/pl_pl.php | 1190 ++ .../yiisoft/yii/framework/i18n/data/ps.php | 368 + .../yiisoft/yii/framework/i18n/data/ps_af.php | 368 + .../yiisoft/yii/framework/i18n/data/pt.php | 1124 + .../yiisoft/yii/framework/i18n/data/pt_ao.php | 1125 + .../yiisoft/yii/framework/i18n/data/pt_br.php | 1124 + .../yiisoft/yii/framework/i18n/data/pt_gw.php | 1124 + .../yiisoft/yii/framework/i18n/data/pt_mz.php | 1125 + .../yiisoft/yii/framework/i18n/data/pt_pt.php | 1125 + .../yiisoft/yii/framework/i18n/data/pt_st.php | 1125 + .../yiisoft/yii/framework/i18n/data/rm.php | 1111 + .../yiisoft/yii/framework/i18n/data/rm_ch.php | 1111 + .../yiisoft/yii/framework/i18n/data/rn.php | 457 + .../yiisoft/yii/framework/i18n/data/rn_bi.php | 457 + .../yiisoft/yii/framework/i18n/data/ro.php | 879 + .../yiisoft/yii/framework/i18n/data/ro_md.php | 879 + .../yiisoft/yii/framework/i18n/data/ro_ro.php | 879 + .../yiisoft/yii/framework/i18n/data/rof.php | 462 + .../yii/framework/i18n/data/rof_tz.php | 462 + .../yiisoft/yii/framework/i18n/data/root.php | 169 + .../yiisoft/yii/framework/i18n/data/ru.php | 1193 ++ .../yiisoft/yii/framework/i18n/data/ru_md.php | 1193 ++ .../yiisoft/yii/framework/i18n/data/ru_ru.php | 1193 ++ .../yiisoft/yii/framework/i18n/data/ru_ua.php | 1193 ++ .../yiisoft/yii/framework/i18n/data/rw.php | 294 + .../yiisoft/yii/framework/i18n/data/rw_rw.php | 294 + .../yiisoft/yii/framework/i18n/data/rwk.php | 462 + .../yii/framework/i18n/data/rwk_tz.php | 462 + .../yiisoft/yii/framework/i18n/data/sa.php | 321 + .../yiisoft/yii/framework/i18n/data/sa_in.php | 321 + .../yiisoft/yii/framework/i18n/data/sah.php | 280 + .../yii/framework/i18n/data/sah_ru.php | 280 + .../yiisoft/yii/framework/i18n/data/saq.php | 462 + .../yii/framework/i18n/data/saq_ke.php | 462 + .../yiisoft/yii/framework/i18n/data/sbp.php | 457 + .../yii/framework/i18n/data/sbp_tz.php | 457 + .../yiisoft/yii/framework/i18n/data/se.php | 590 + .../yiisoft/yii/framework/i18n/data/se_fi.php | 590 + .../yiisoft/yii/framework/i18n/data/se_no.php | 590 + .../yiisoft/yii/framework/i18n/data/seh.php | 461 + .../yii/framework/i18n/data/seh_mz.php | 461 + .../yiisoft/yii/framework/i18n/data/ses.php | 456 + .../yii/framework/i18n/data/ses_ml.php | 456 + .../yiisoft/yii/framework/i18n/data/sg.php | 456 + .../yiisoft/yii/framework/i18n/data/sg_cf.php | 456 + .../yiisoft/yii/framework/i18n/data/sh.php | 328 + .../yiisoft/yii/framework/i18n/data/sh_ba.php | 328 + .../yiisoft/yii/framework/i18n/data/sh_cs.php | 328 + .../yiisoft/yii/framework/i18n/data/sh_yu.php | 328 + .../yiisoft/yii/framework/i18n/data/shi.php | 462 + .../yii/framework/i18n/data/shi_latn.php | 462 + .../yii/framework/i18n/data/shi_latn_ma.php | 462 + .../yii/framework/i18n/data/shi_ma.php | 327 + .../yii/framework/i18n/data/shi_tfng.php | 462 + .../yii/framework/i18n/data/shi_tfng_ma.php | 462 + .../yiisoft/yii/framework/i18n/data/si.php | 529 + .../yiisoft/yii/framework/i18n/data/si_lk.php | 529 + .../yiisoft/yii/framework/i18n/data/sid.php | 192 + .../yii/framework/i18n/data/sid_et.php | 192 + .../yiisoft/yii/framework/i18n/data/sk.php | 871 + .../yiisoft/yii/framework/i18n/data/sk_sk.php | 871 + .../yiisoft/yii/framework/i18n/data/sl.php | 1118 + .../yiisoft/yii/framework/i18n/data/sl_si.php | 1118 + .../yiisoft/yii/framework/i18n/data/sn.php | 460 + .../yiisoft/yii/framework/i18n/data/sn_zw.php | 460 + .../yiisoft/yii/framework/i18n/data/so.php | 545 + .../yiisoft/yii/framework/i18n/data/so_dj.php | 546 + .../yiisoft/yii/framework/i18n/data/so_et.php | 546 + .../yiisoft/yii/framework/i18n/data/so_ke.php | 546 + .../yiisoft/yii/framework/i18n/data/so_so.php | 545 + .../yiisoft/yii/framework/i18n/data/sq.php | 460 + .../yiisoft/yii/framework/i18n/data/sq_al.php | 460 + .../yiisoft/yii/framework/i18n/data/sr.php | 1124 + .../yiisoft/yii/framework/i18n/data/sr_ba.php | 328 + .../yiisoft/yii/framework/i18n/data/sr_cs.php | 328 + .../yii/framework/i18n/data/sr_cyrl.php | 1124 + .../yii/framework/i18n/data/sr_cyrl_ba.php | 1112 + .../yii/framework/i18n/data/sr_cyrl_cs.php | 328 + .../yii/framework/i18n/data/sr_cyrl_me.php | 1124 + .../yii/framework/i18n/data/sr_cyrl_rs.php | 1124 + .../yii/framework/i18n/data/sr_cyrl_yu.php | 328 + .../yii/framework/i18n/data/sr_latn.php | 1124 + .../yii/framework/i18n/data/sr_latn_ba.php | 1124 + .../yii/framework/i18n/data/sr_latn_cs.php | 328 + .../yii/framework/i18n/data/sr_latn_me.php | 1124 + .../yii/framework/i18n/data/sr_latn_rs.php | 1124 + .../yii/framework/i18n/data/sr_latn_yu.php | 328 + .../yiisoft/yii/framework/i18n/data/sr_me.php | 328 + .../yiisoft/yii/framework/i18n/data/sr_rs.php | 328 + .../yiisoft/yii/framework/i18n/data/sr_yu.php | 328 + .../yiisoft/yii/framework/i18n/data/ss.php | 190 + .../yiisoft/yii/framework/i18n/data/ss_sz.php | 190 + .../yiisoft/yii/framework/i18n/data/ss_za.php | 190 + .../yiisoft/yii/framework/i18n/data/ssy.php | 199 + .../yii/framework/i18n/data/ssy_er.php | 199 + .../yiisoft/yii/framework/i18n/data/st.php | 281 + .../yiisoft/yii/framework/i18n/data/st_ls.php | 282 + .../yiisoft/yii/framework/i18n/data/st_za.php | 281 + .../yiisoft/yii/framework/i18n/data/sv.php | 1216 ++ .../yiisoft/yii/framework/i18n/data/sv_fi.php | 1216 ++ .../yiisoft/yii/framework/i18n/data/sv_se.php | 1216 ++ .../yiisoft/yii/framework/i18n/data/sw.php | 689 + .../yiisoft/yii/framework/i18n/data/sw_ke.php | 689 + .../yiisoft/yii/framework/i18n/data/sw_tz.php | 689 + .../yiisoft/yii/framework/i18n/data/swc.php | 457 + .../yii/framework/i18n/data/swc_cd.php | 457 + .../yiisoft/yii/framework/i18n/data/syr.php | 321 + .../yii/framework/i18n/data/syr_sy.php | 321 + .../yiisoft/yii/framework/i18n/data/ta.php | 1172 + .../yiisoft/yii/framework/i18n/data/ta_in.php | 1172 + .../yiisoft/yii/framework/i18n/data/ta_lk.php | 1173 + .../yiisoft/yii/framework/i18n/data/te.php | 1154 + .../yiisoft/yii/framework/i18n/data/te_in.php | 1154 + .../yiisoft/yii/framework/i18n/data/teo.php | 462 + .../yii/framework/i18n/data/teo_ke.php | 463 + .../yii/framework/i18n/data/teo_ug.php | 462 + .../yiisoft/yii/framework/i18n/data/tg.php | 249 + .../yii/framework/i18n/data/tg_cyrl.php | 249 + .../yii/framework/i18n/data/tg_cyrl_tj.php | 249 + .../yiisoft/yii/framework/i18n/data/tg_tj.php | 322 + .../yiisoft/yii/framework/i18n/data/th.php | 1127 + .../yiisoft/yii/framework/i18n/data/th_th.php | 1127 + .../yiisoft/yii/framework/i18n/data/ti.php | 557 + .../yiisoft/yii/framework/i18n/data/ti_er.php | 558 + .../yiisoft/yii/framework/i18n/data/ti_et.php | 557 + .../yiisoft/yii/framework/i18n/data/tig.php | 467 + .../yii/framework/i18n/data/tig_er.php | 467 + .../yiisoft/yii/framework/i18n/data/tl.php | 326 + .../yiisoft/yii/framework/i18n/data/tl_ph.php | 326 + .../yiisoft/yii/framework/i18n/data/tn.php | 268 + .../yiisoft/yii/framework/i18n/data/tn_za.php | 268 + .../yiisoft/yii/framework/i18n/data/to.php | 692 + .../yiisoft/yii/framework/i18n/data/to_to.php | 692 + .../yiisoft/yii/framework/i18n/data/tr.php | 1187 ++ .../yiisoft/yii/framework/i18n/data/tr_tr.php | 1187 ++ .../yiisoft/yii/framework/i18n/data/trv.php | 235 + .../yii/framework/i18n/data/trv_tw.php | 235 + .../yiisoft/yii/framework/i18n/data/ts.php | 213 + .../yiisoft/yii/framework/i18n/data/ts_za.php | 213 + .../yiisoft/yii/framework/i18n/data/tt.php | 322 + .../yiisoft/yii/framework/i18n/data/tt_ru.php | 322 + .../yiisoft/yii/framework/i18n/data/twq.php | 456 + .../yii/framework/i18n/data/twq_ne.php | 456 + .../yiisoft/yii/framework/i18n/data/tzm.php | 461 + .../yii/framework/i18n/data/tzm_latn.php | 461 + .../yii/framework/i18n/data/tzm_latn_ma.php | 461 + .../yii/framework/i18n/data/tzm_ma.php | 321 + .../yiisoft/yii/framework/i18n/data/ug.php | 321 + .../yii/framework/i18n/data/ug_arab.php | 321 + .../yii/framework/i18n/data/ug_arab_cn.php | 321 + .../yiisoft/yii/framework/i18n/data/ug_cn.php | 321 + .../yiisoft/yii/framework/i18n/data/uk.php | 1163 + .../yiisoft/yii/framework/i18n/data/uk_ua.php | 1163 + .../yiisoft/yii/framework/i18n/data/ur.php | 683 + .../yiisoft/yii/framework/i18n/data/ur_in.php | 683 + .../yiisoft/yii/framework/i18n/data/ur_pk.php | 683 + .../yiisoft/yii/framework/i18n/data/uz.php | 216 + .../yiisoft/yii/framework/i18n/data/uz_af.php | 322 + .../yii/framework/i18n/data/uz_arab.php | 219 + .../yii/framework/i18n/data/uz_arab_af.php | 219 + .../yii/framework/i18n/data/uz_cyrl.php | 216 + .../yii/framework/i18n/data/uz_cyrl_uz.php | 216 + .../yii/framework/i18n/data/uz_latn.php | 216 + .../yii/framework/i18n/data/uz_latn_uz.php | 216 + .../yiisoft/yii/framework/i18n/data/uz_uz.php | 322 + .../yiisoft/yii/framework/i18n/data/vai.php | 456 + .../yii/framework/i18n/data/vai_latn.php | 457 + .../yii/framework/i18n/data/vai_latn_lr.php | 457 + .../yii/framework/i18n/data/vai_vaii.php | 456 + .../yii/framework/i18n/data/vai_vaii_lr.php | 456 + .../yiisoft/yii/framework/i18n/data/ve.php | 189 + .../yiisoft/yii/framework/i18n/data/ve_za.php | 189 + .../yiisoft/yii/framework/i18n/data/vi.php | 696 + .../yiisoft/yii/framework/i18n/data/vi_vn.php | 696 + .../yiisoft/yii/framework/i18n/data/vun.php | 462 + .../yii/framework/i18n/data/vun_tz.php | 462 + .../yiisoft/yii/framework/i18n/data/wae.php | 730 + .../yii/framework/i18n/data/wae_ch.php | 730 + .../yiisoft/yii/framework/i18n/data/wal.php | 332 + .../yii/framework/i18n/data/wal_et.php | 332 + .../yiisoft/yii/framework/i18n/data/wo.php | 321 + .../yii/framework/i18n/data/wo_latn.php | 321 + .../yii/framework/i18n/data/wo_latn_sn.php | 321 + .../yiisoft/yii/framework/i18n/data/wo_sn.php | 321 + .../yiisoft/yii/framework/i18n/data/xh.php | 293 + .../yiisoft/yii/framework/i18n/data/xh_za.php | 293 + .../yiisoft/yii/framework/i18n/data/xog.php | 461 + .../yii/framework/i18n/data/xog_ug.php | 461 + .../yiisoft/yii/framework/i18n/data/yav.php | 455 + .../yii/framework/i18n/data/yav_cm.php | 455 + .../yiisoft/yii/framework/i18n/data/yo.php | 511 + .../yiisoft/yii/framework/i18n/data/yo_ng.php | 511 + .../yiisoft/yii/framework/i18n/data/zh.php | 1169 + .../yiisoft/yii/framework/i18n/data/zh_cn.php | 351 + .../yii/framework/i18n/data/zh_hans.php | 1169 + .../yii/framework/i18n/data/zh_hans_cn.php | 1169 + .../yii/framework/i18n/data/zh_hans_hk.php | 1169 + .../yii/framework/i18n/data/zh_hans_mo.php | 1169 + .../yii/framework/i18n/data/zh_hans_sg.php | 1169 + .../yii/framework/i18n/data/zh_hant.php | 1185 ++ .../yii/framework/i18n/data/zh_hant_hk.php | 1185 ++ .../yii/framework/i18n/data/zh_hant_mo.php | 1185 ++ .../yii/framework/i18n/data/zh_hant_tw.php | 1185 ++ .../yiisoft/yii/framework/i18n/data/zh_hk.php | 351 + .../yiisoft/yii/framework/i18n/data/zh_mo.php | 351 + .../yiisoft/yii/framework/i18n/data/zh_sg.php | 351 + .../yiisoft/yii/framework/i18n/data/zh_tw.php | 351 + .../yiisoft/yii/framework/i18n/data/zu.php | 697 + .../yiisoft/yii/framework/i18n/data/zu_za.php | 697 + .../framework/i18n/gettext/CGettextFile.php | 35 + .../framework/i18n/gettext/CGettextMoFile.php | 272 + .../framework/i18n/gettext/CGettextPoFile.php | 98 + .../framework/logging/CChainedLogFilter.php | 39 + .../yii/framework/logging/CDbLogRoute.php | 139 + .../yii/framework/logging/CEmailLogRoute.php | 174 + .../yii/framework/logging/CFileLogRoute.php | 203 + .../yii/framework/logging/CLogFilter.php | 120 + .../yii/framework/logging/CLogRoute.php | 121 + .../yii/framework/logging/CLogRouter.php | 126 + .../yiisoft/yii/framework/logging/CLogger.php | 354 + .../framework/logging/CProfileLogRoute.php | 205 + .../yii/framework/logging/CWebLogRoute.php | 85 + .../yiisoft/yii/framework/messages/ar/zii.php | 36 + .../yiisoft/yii/framework/messages/bg/yii.php | 244 + .../yiisoft/yii/framework/messages/bg/zii.php | 38 + .../yiisoft/yii/framework/messages/bs/yii.php | 231 + .../yiisoft/yii/framework/messages/ca/yii.php | 270 + .../yiisoft/yii/framework/messages/ca/zii.php | 41 + .../yiisoft/yii/framework/messages/config.php | 22 + .../yiisoft/yii/framework/messages/cs/yii.php | 249 + .../yiisoft/yii/framework/messages/cs/zii.php | 36 + .../yiisoft/yii/framework/messages/de/yii.php | 280 + .../yiisoft/yii/framework/messages/de/zii.php | 41 + .../yiisoft/yii/framework/messages/el/yii.php | 270 + .../yiisoft/yii/framework/messages/el/zii.php | 41 + .../yiisoft/yii/framework/messages/es/yii.php | 269 + .../yiisoft/yii/framework/messages/es/zii.php | 41 + .../yii/framework/messages/fa_ir/yii.php | 233 + .../yii/framework/messages/fa_ir/zii.php | 37 + .../yiisoft/yii/framework/messages/fi/yii.php | 283 + .../yiisoft/yii/framework/messages/fi/zii.php | 42 + .../yiisoft/yii/framework/messages/fr/yii.php | 253 + .../yiisoft/yii/framework/messages/fr/zii.php | 39 + .../yiisoft/yii/framework/messages/he/yii.php | 239 + .../yiisoft/yii/framework/messages/he/zii.php | 35 + .../yiisoft/yii/framework/messages/hu/yii.php | 212 + .../yiisoft/yii/framework/messages/hu/zii.php | 36 + .../yiisoft/yii/framework/messages/id/yii.php | 254 + .../yiisoft/yii/framework/messages/id/zii.php | 36 + .../yiisoft/yii/framework/messages/it/yii.php | 211 + .../yiisoft/yii/framework/messages/it/zii.php | 36 + .../yiisoft/yii/framework/messages/ja/yii.php | 283 + .../yiisoft/yii/framework/messages/ja/zii.php | 41 + .../yiisoft/yii/framework/messages/kk/yii.php | 280 + .../yiisoft/yii/framework/messages/kk/zii.php | 41 + .../yii/framework/messages/ko_kr/yii.php | 255 + .../yii/framework/messages/ko_kr/zii.php | 39 + .../yiisoft/yii/framework/messages/lt/yii.php | 254 + .../yiisoft/yii/framework/messages/lt/zii.php | 39 + .../yiisoft/yii/framework/messages/lv/yii.php | 232 + .../yiisoft/yii/framework/messages/lv/zii.php | 34 + .../yiisoft/yii/framework/messages/nl/yii.php | 280 + .../yiisoft/yii/framework/messages/nl/zii.php | 41 + .../yiisoft/yii/framework/messages/no/yii.php | 220 + .../yiisoft/yii/framework/messages/pl/yii.php | 254 + .../yiisoft/yii/framework/messages/pl/zii.php | 36 + .../yiisoft/yii/framework/messages/pt/yii.php | 279 + .../yiisoft/yii/framework/messages/pt/zii.php | 36 + .../yii/framework/messages/pt_br/yii.php | 279 + .../yii/framework/messages/pt_br/zii.php | 36 + .../yiisoft/yii/framework/messages/ro/yii.php | 211 + .../yiisoft/yii/framework/messages/ro/zii.php | 39 + .../yiisoft/yii/framework/messages/ru/yii.php | 283 + .../yiisoft/yii/framework/messages/ru/zii.php | 41 + .../yiisoft/yii/framework/messages/sk/yii.php | 283 + .../yiisoft/yii/framework/messages/sk/zii.php | 41 + .../yii/framework/messages/sr_sr/yii.php | 203 + .../yii/framework/messages/sr_sr/zii.php | 36 + .../yii/framework/messages/sr_yu/yii.php | 203 + .../yii/framework/messages/sr_yu/zii.php | 36 + .../yiisoft/yii/framework/messages/sv/yii.php | 254 + .../yiisoft/yii/framework/messages/sv/zii.php | 36 + .../yii/framework/messages/ta_in/yii.php | 249 + .../yii/framework/messages/ta_in/zii.php | 36 + .../yiisoft/yii/framework/messages/th/yii.php | 211 + .../yiisoft/yii/framework/messages/tr/yii.php | 236 + .../yiisoft/yii/framework/messages/tr/zii.php | 36 + .../yiisoft/yii/framework/messages/uk/yii.php | 265 + .../yiisoft/yii/framework/messages/uk/zii.php | 36 + .../yiisoft/yii/framework/messages/vi/yii.php | 253 + .../yiisoft/yii/framework/messages/vi/zii.php | 39 + .../yii/framework/messages/zh_cn/yii.php | 260 + .../yii/framework/messages/zh_cn/zii.php | 36 + .../yii/framework/messages/zh_tw/yii.php | 205 + .../yii/framework/messages/zh_tw/zii.php | 36 + .../yii/framework/test/CDbFixtureManager.php | 365 + .../yii/framework/test/CDbTestCase.php | 120 + .../yiisoft/yii/framework/test/CTestCase.php | 32 + .../yii/framework/test/CWebTestCase.php | 106 + .../yii/framework/utils/CDateTimeParser.php | 350 + .../yii/framework/utils/CFileHelper.php | 311 + .../yii/framework/utils/CFormatter.php | 339 + .../framework/utils/CLocalizedFormatter.php | 131 + .../yii/framework/utils/CMarkdownParser.php | 208 + .../yii/framework/utils/CPasswordHelper.php | 211 + .../yii/framework/utils/CPropertyValue.php | 157 + .../yii/framework/utils/CTimestamp.php | 376 + .../yii/framework/utils/CVarDumper.php | 140 + .../yiisoft/yii/framework/utils/mimeTypes.php | 188 + .../validators/CBooleanValidator.php | 92 + .../validators/CCaptchaValidator.php | 124 + .../validators/CCompareValidator.php | 202 + .../framework/validators/CDateValidator.php | 81 + .../validators/CDefaultValueValidator.php | 50 + .../framework/validators/CEmailValidator.php | 195 + .../framework/validators/CExistValidator.php | 119 + .../framework/validators/CFileValidator.php | 305 + .../framework/validators/CFilterValidator.php | 49 + .../framework/validators/CInlineValidator.php | 82 + .../framework/validators/CNumberValidator.php | 183 + .../framework/validators/CRangeValidator.php | 110 + .../CRegularExpressionValidator.php | 98 + .../validators/CRequiredValidator.php | 118 + .../framework/validators/CSafeValidator.php | 30 + .../framework/validators/CStringValidator.php | 183 + .../framework/validators/CTypeValidator.php | 132 + .../framework/validators/CUniqueValidator.php | 151 + .../framework/validators/CUnsafeValidator.php | 36 + .../framework/validators/CUrlValidator.php | 186 + .../yii/framework/validators/CValidator.php | 279 + .../framework/vendors/Net_IDNA2/LICENSE.txt | 165 + .../framework/vendors/Net_IDNA2/Net/IDNA2.php | 3402 +++ .../vendors/Net_IDNA2/Net/IDNA2/Exception.php | 4 + .../Net/IDNA2/Exception/Nameprep.php | 6 + .../yiisoft/yii/framework/vendors/README.html | 119 + .../TextHighlighter/Text/Highlighter.php | 397 + .../TextHighlighter/Text/Highlighter/ABAP.php | 505 + .../TextHighlighter/Text/Highlighter/CPP.php | 840 + .../TextHighlighter/Text/Highlighter/CSS.php | 419 + .../TextHighlighter/Text/Highlighter/DIFF.php | 366 + .../TextHighlighter/Text/Highlighter/DTD.php | 408 + .../Text/Highlighter/Generator.php | 1254 ++ .../TextHighlighter/Text/Highlighter/HTML.php | 220 + .../TextHighlighter/Text/Highlighter/JAVA.php | 784 + .../Text/Highlighter/JAVASCRIPT.php | 613 + .../Text/Highlighter/MYSQL.php | 416 + .../TextHighlighter/Text/Highlighter/PERL.php | 1334 ++ .../TextHighlighter/Text/Highlighter/PHP.php | 1089 + .../Text/Highlighter/PYTHON.php | 629 + .../TextHighlighter/Text/Highlighter/RUBY.php | 807 + .../Text/Highlighter/Renderer.php | 152 + .../Text/Highlighter/Renderer/Array.php | 199 + .../Text/Highlighter/Renderer/BB.php | 238 + .../Text/Highlighter/Renderer/Console.php | 208 + .../Text/Highlighter/Renderer/Html.php | 454 + .../Text/Highlighter/Renderer/HtmlTags.php | 187 + .../Text/Highlighter/Renderer/JSON.php | 86 + .../Text/Highlighter/Renderer/XML.php | 103 + .../TextHighlighter/Text/Highlighter/SH.php | 1207 ++ .../TextHighlighter/Text/Highlighter/SQL.php | 401 + .../Text/Highlighter/VBSCRIPT.php | 300 + .../TextHighlighter/Text/Highlighter/XML.php | 245 + .../vendors/TextHighlighter/Text/README | 455 + .../vendors/TextHighlighter/Text/TODO | 12 + .../vendors/TextHighlighter/Text/abap.xml | 802 + .../vendors/TextHighlighter/Text/cpp.xml | 201 + .../vendors/TextHighlighter/Text/css.xml | 368 + .../vendors/TextHighlighter/Text/diff.xml | 45 + .../vendors/TextHighlighter/Text/dtd.xml | 66 + .../vendors/TextHighlighter/Text/generate | 171 + .../vendors/TextHighlighter/Text/generate.bat | 188 + .../vendors/TextHighlighter/Text/html.xml | 33 + .../vendors/TextHighlighter/Text/java.xml | 2824 +++ .../TextHighlighter/Text/javascript.xml | 174 + .../vendors/TextHighlighter/Text/mysql.xml | 424 + .../vendors/TextHighlighter/Text/package.xml | 243 + .../vendors/TextHighlighter/Text/perl.xml | 439 + .../vendors/TextHighlighter/Text/php.xml | 194 + .../vendors/TextHighlighter/Text/python.xml | 229 + .../vendors/TextHighlighter/Text/ruby.xml | 141 + .../vendors/TextHighlighter/Text/sample.css | 57 + .../vendors/TextHighlighter/Text/sh.xml | 242 + .../vendors/TextHighlighter/Text/sql.xml | 496 + .../vendors/TextHighlighter/Text/vbscript.xml | 305 + .../vendors/TextHighlighter/Text/xml.xml | 37 + .../vendors/TextHighlighter/highlight.css | 383 + .../yii/framework/vendors/adodb/LICENSE.txt | 182 + .../yii/framework/vendors/bbq/LICENSE.txt | 22 + .../yii/framework/vendors/cldr/LICENSE.txt | 33 + .../vendors/console-normalizer/README.md | 86 + .../normalizeconsole.min.js | 1 + .../yii/framework/vendors/gettext/LICENSE.txt | 22 + .../yii/framework/vendors/history/license.txt | 10 + .../htmlpurifier/HTMLPurifier.standalone.php | 17627 ++++++++++++++++ .../vendors/htmlpurifier/LICENSE.txt | 504 + .../ConfigSchema/Builder/ConfigSchema.php | 44 + .../HTMLPurifier/ConfigSchema/Builder/Xml.php | 106 + .../HTMLPurifier/ConfigSchema/Exception.php | 11 + .../HTMLPurifier/ConfigSchema/Interchange.php | 42 + .../ConfigSchema/Interchange/Directive.php | 77 + .../ConfigSchema/Interchange/Id.php | 37 + .../ConfigSchema/InterchangeBuilder.php | 180 + .../HTMLPurifier/ConfigSchema/Validator.php | 206 + .../ConfigSchema/ValidatorAtom.php | 66 + .../HTMLPurifier/ConfigSchema/schema.ser | Bin 0 -> 14880 bytes .../schema/Attr.AllowedClasses.txt | 8 + .../schema/Attr.AllowedFrameTargets.txt | 12 + .../ConfigSchema/schema/Attr.AllowedRel.txt | 9 + .../ConfigSchema/schema/Attr.AllowedRev.txt | 9 + .../schema/Attr.ClassUseCDATA.txt | 19 + .../schema/Attr.DefaultImageAlt.txt | 11 + .../schema/Attr.DefaultInvalidImage.txt | 9 + .../schema/Attr.DefaultInvalidImageAlt.txt | 8 + .../schema/Attr.DefaultTextDir.txt | 10 + .../ConfigSchema/schema/Attr.EnableID.txt | 16 + .../schema/Attr.ForbiddenClasses.txt | 8 + .../ConfigSchema/schema/Attr.IDBlacklist.txt | 5 + .../schema/Attr.IDBlacklistRegexp.txt | 9 + .../ConfigSchema/schema/Attr.IDPrefix.txt | 12 + .../schema/Attr.IDPrefixLocal.txt | 14 + .../schema/AutoFormat.AutoParagraph.txt | 31 + .../ConfigSchema/schema/AutoFormat.Custom.txt | 12 + .../schema/AutoFormat.DisplayLinkURI.txt | 11 + .../schema/AutoFormat.Linkify.txt | 12 + .../AutoFormat.PurifierLinkify.DocURL.txt | 12 + .../schema/AutoFormat.PurifierLinkify.txt | 12 + ...rmat.RemoveEmpty.RemoveNbsp.Exceptions.txt | 11 + .../AutoFormat.RemoveEmpty.RemoveNbsp.txt | 15 + .../schema/AutoFormat.RemoveEmpty.txt | 46 + ...utoFormat.RemoveSpansWithoutAttributes.txt | 11 + .../schema/CSS.AllowImportant.txt | 8 + .../ConfigSchema/schema/CSS.AllowTricky.txt | 11 + .../ConfigSchema/schema/CSS.AllowedFonts.txt | 12 + .../schema/CSS.AllowedProperties.txt | 18 + .../ConfigSchema/schema/CSS.DefinitionRev.txt | 11 + .../schema/CSS.ForbiddenProperties.txt | 13 + .../ConfigSchema/schema/CSS.MaxImgLength.txt | 16 + .../ConfigSchema/schema/CSS.Proprietary.txt | 10 + .../ConfigSchema/schema/CSS.Trusted.txt | 9 + .../schema/Cache.DefinitionImpl.txt | 14 + .../schema/Cache.SerializerPath.txt | 13 + .../schema/Cache.SerializerPermissions.txt | 11 + .../schema/Core.AggressivelyFixLt.txt | 18 + .../schema/Core.CollectErrors.txt | 12 + .../schema/Core.ColorKeywords.txt | 29 + .../schema/Core.ConvertDocumentToFragment.txt | 14 + .../Core.DirectLexLineNumberSyncInterval.txt | 17 + .../schema/Core.DisableExcludes.txt | 14 + .../ConfigSchema/schema/Core.EnableIDNA.txt | 9 + .../ConfigSchema/schema/Core.Encoding.txt | 15 + .../schema/Core.EscapeInvalidChildren.txt | 10 + .../schema/Core.EscapeInvalidTags.txt | 7 + .../schema/Core.EscapeNonASCIICharacters.txt | 13 + .../schema/Core.HiddenElements.txt | 19 + .../ConfigSchema/schema/Core.Language.txt | 10 + .../ConfigSchema/schema/Core.LexerImpl.txt | 34 + .../schema/Core.MaintainLineNumbers.txt | 16 + .../schema/Core.NormalizeNewlines.txt | 11 + .../schema/Core.RemoveInvalidImg.txt | 12 + .../Core.RemoveProcessingInstructions.txt | 11 + .../schema/Core.RemoveScriptContents.txt | 12 + .../ConfigSchema/schema/Filter.Custom.txt | 11 + .../Filter.ExtractStyleBlocks.Escaping.txt | 14 + .../Filter.ExtractStyleBlocks.Scope.txt | 29 + .../Filter.ExtractStyleBlocks.TidyImpl.txt | 16 + .../schema/Filter.ExtractStyleBlocks.txt | 74 + .../ConfigSchema/schema/Filter.YouTube.txt | 16 + .../ConfigSchema/schema/HTML.Allowed.txt | 25 + .../schema/HTML.AllowedAttributes.txt | 19 + .../schema/HTML.AllowedComments.txt | 10 + .../schema/HTML.AllowedCommentsRegexp.txt | 15 + .../schema/HTML.AllowedElements.txt | 23 + .../schema/HTML.AllowedModules.txt | 20 + .../schema/HTML.Attr.Name.UseCDATA.txt | 11 + .../ConfigSchema/schema/HTML.BlockWrapper.txt | 18 + .../ConfigSchema/schema/HTML.CoreModules.txt | 23 + .../schema/HTML.CustomDoctype.txt | 9 + .../ConfigSchema/schema/HTML.DefinitionID.txt | 33 + .../schema/HTML.DefinitionRev.txt | 16 + .../ConfigSchema/schema/HTML.Doctype.txt | 11 + .../schema/HTML.FlashAllowFullScreen.txt | 11 + .../schema/HTML.ForbiddenAttributes.txt | 21 + .../schema/HTML.ForbiddenElements.txt | 20 + .../ConfigSchema/schema/HTML.MaxImgLength.txt | 14 + .../ConfigSchema/schema/HTML.Nofollow.txt | 7 + .../ConfigSchema/schema/HTML.Parent.txt | 12 + .../ConfigSchema/schema/HTML.Proprietary.txt | 12 + .../ConfigSchema/schema/HTML.SafeEmbed.txt | 13 + .../ConfigSchema/schema/HTML.SafeIframe.txt | 13 + .../ConfigSchema/schema/HTML.SafeObject.txt | 13 + .../schema/HTML.SafeScripting.txt | 10 + .../ConfigSchema/schema/HTML.Strict.txt | 9 + .../ConfigSchema/schema/HTML.TargetBlank.txt | 8 + .../ConfigSchema/schema/HTML.TidyAdd.txt | 8 + .../ConfigSchema/schema/HTML.TidyLevel.txt | 24 + .../ConfigSchema/schema/HTML.TidyRemove.txt | 8 + .../ConfigSchema/schema/HTML.Trusted.txt | 9 + .../ConfigSchema/schema/HTML.XHTML.txt | 11 + .../schema/Output.CommentScriptContents.txt | 10 + .../schema/Output.FixInnerHTML.txt | 15 + .../schema/Output.FlashCompat.txt | 11 + .../ConfigSchema/schema/Output.Newline.txt | 13 + .../ConfigSchema/schema/Output.SortAttr.txt | 14 + .../ConfigSchema/schema/Output.TidyFormat.txt | 25 + .../ConfigSchema/schema/Test.ForceNoIconv.txt | 7 + .../schema/URI.AllowedSchemes.txt | 17 + .../ConfigSchema/schema/URI.Base.txt | 17 + .../ConfigSchema/schema/URI.DefaultScheme.txt | 10 + .../ConfigSchema/schema/URI.DefinitionID.txt | 11 + .../ConfigSchema/schema/URI.DefinitionRev.txt | 11 + .../ConfigSchema/schema/URI.Disable.txt | 14 + .../schema/URI.DisableExternal.txt | 11 + .../schema/URI.DisableExternalResources.txt | 13 + .../schema/URI.DisableResources.txt | 15 + .../ConfigSchema/schema/URI.Host.txt | 19 + .../ConfigSchema/schema/URI.HostBlacklist.txt | 9 + .../ConfigSchema/schema/URI.MakeAbsolute.txt | 13 + .../ConfigSchema/schema/URI.Munge.txt | 83 + .../schema/URI.MungeResources.txt | 17 + .../schema/URI.MungeSecretKey.txt | 30 + .../schema/URI.OverrideAllowedSchemes.txt | 9 + .../schema/URI.SafeIframeRegexp.txt | 22 + .../HTMLPurifier/ConfigSchema/schema/info.ini | 3 + .../HTMLPurifier/EntityLookup/entities.ser | 1 + .../Filter/ExtractStyleBlocks.php | 289 + .../HTMLPurifier/Filter/YouTube.php | 39 + .../Language/classes/en-x-test.php | 12 + .../Language/messages/en-x-test.php | 11 + .../Language/messages/en-x-testmini.php | 12 + .../HTMLPurifier/Language/messages/en.php | 63 + .../standalone/HTMLPurifier/Lexer/PH5P.php | 3904 ++++ .../standalone/HTMLPurifier/Printer.php | 176 + .../HTMLPurifier/Printer/CSSDefinition.php | 38 + .../HTMLPurifier/Printer/ConfigForm.css | 10 + .../HTMLPurifier/Printer/ConfigForm.js | 5 + .../HTMLPurifier/Printer/ConfigForm.php | 368 + .../HTMLPurifier/Printer/HTMLDefinition.php | 272 + .../yii/framework/vendors/jquery/LICENSE.txt | 21 + .../vendors/jquery/autocomplete/LICENSE.txt | 20 + .../vendors/jquery/maskedinput/LICENSE.txt | 22 + .../vendors/jquery/treeview/LICENSE.txt | 20 + .../vendors/jqueryui/MIT-LICENSE.txt | 26 + .../yii/framework/vendors/json/LICENSE.txt | 22 + .../framework/vendors/markdown/LICENSE.txt | 36 + .../framework/vendors/markdown/markdown.php | 2648 +++ .../vendors/punycode/LICENSE-GPL.txt | 278 + .../vendors/punycode/LICENSE-MIT.txt | 20 + .../yiisoft/yii/framework/views/ar/error.php | 37 + .../yii/framework/views/ar/error400.php | 33 + .../yii/framework/views/ar/error403.php | 32 + .../yii/framework/views/ar/error404.php | 33 + .../yii/framework/views/ar/error500.php | 35 + .../yii/framework/views/ar/error503.php | 30 + .../yii/framework/views/ar/exception.php | 242 + .../yii/framework/views/ar/log-firebug.php | 23 + .../yiisoft/yii/framework/views/ar/log.php | 40 + .../views/ar/profile-callstack-firebug.php | 19 + .../framework/views/ar/profile-callstack.php | 30 + .../views/ar/profile-summary-firebug.php | 22 + .../framework/views/ar/profile-summary.php | 41 + .../yiisoft/yii/framework/views/bg/error.php | 37 + .../yii/framework/views/bg/error400.php | 33 + .../yii/framework/views/bg/error403.php | 32 + .../yii/framework/views/bg/error404.php | 32 + .../yii/framework/views/bg/error500.php | 35 + .../yii/framework/views/bg/error503.php | 30 + .../yii/framework/views/bg/log-firebug.php | 23 + .../yiisoft/yii/framework/views/bg/log.php | 32 + .../views/bg/profile-callstack-firebug.php | 19 + .../framework/views/bg/profile-callstack.php | 30 + .../views/bg/profile-summary-firebug.php | 22 + .../framework/views/bg/profile-summary.php | 41 + .../yiisoft/yii/framework/views/ca/error.php | 37 + .../yii/framework/views/ca/error400.php | 33 + .../yii/framework/views/ca/error403.php | 32 + .../yii/framework/views/ca/error404.php | 33 + .../yii/framework/views/ca/error500.php | 35 + .../yii/framework/views/ca/error503.php | 31 + .../yii/framework/views/ca/log-firebug.php | 23 + .../yiisoft/yii/framework/views/ca/log.php | 40 + .../views/ca/profile-callstack-firebug.php | 19 + .../framework/views/ca/profile-callstack.php | 30 + .../views/ca/profile-summary-firebug.php | 22 + .../framework/views/ca/profile-summary.php | 41 + .../yiisoft/yii/framework/views/de/error.php | 38 + .../yii/framework/views/de/error400.php | 34 + .../yii/framework/views/de/error403.php | 33 + .../yii/framework/views/de/error404.php | 34 + .../yii/framework/views/de/error500.php | 35 + .../yii/framework/views/de/error503.php | 31 + .../yii/framework/views/de/log-firebug.php | 23 + .../yiisoft/yii/framework/views/de/log.php | 40 + .../views/de/profile-callstack-firebug.php | 19 + .../framework/views/de/profile-callstack.php | 30 + .../views/de/profile-summary-firebug.php | 23 + .../framework/views/de/profile-summary.php | 41 + .../yiisoft/yii/framework/views/el/error.php | 37 + .../yii/framework/views/el/error400.php | 33 + .../yii/framework/views/el/error403.php | 32 + .../yii/framework/views/el/error404.php | 33 + .../yii/framework/views/el/error500.php | 35 + .../yii/framework/views/el/error503.php | 31 + .../yii/framework/views/el/log-firebug.php | 23 + .../yiisoft/yii/framework/views/el/log.php | 40 + .../views/el/profile-callstack-firebug.php | 19 + .../framework/views/el/profile-callstack.php | 30 + .../views/el/profile-summary-firebug.php | 22 + .../framework/views/el/profile-summary.php | 41 + .../yiisoft/yii/framework/views/error.php | 37 + .../yiisoft/yii/framework/views/error400.php | 33 + .../yiisoft/yii/framework/views/error403.php | 32 + .../yiisoft/yii/framework/views/error404.php | 33 + .../yiisoft/yii/framework/views/error500.php | 35 + .../yiisoft/yii/framework/views/error503.php | 31 + .../yiisoft/yii/framework/views/es/error.php | 37 + .../yii/framework/views/es/error400.php | 33 + .../yii/framework/views/es/error403.php | 32 + .../yii/framework/views/es/error404.php | 33 + .../yii/framework/views/es/error500.php | 37 + .../yii/framework/views/es/error503.php | 31 + .../yii/framework/views/es/log-firebug.php | 23 + .../yiisoft/yii/framework/views/es/log.php | 40 + .../views/es/profile-callstack-firebug.php | 19 + .../framework/views/es/profile-callstack.php | 30 + .../views/es/profile-summary-firebug.php | 22 + .../framework/views/es/profile-summary.php | 41 + .../yiisoft/yii/framework/views/exception.php | 242 + .../yiisoft/yii/framework/views/fi/error.php | 37 + .../yii/framework/views/fi/error400.php | 33 + .../yii/framework/views/fi/error403.php | 32 + .../yii/framework/views/fi/error404.php | 33 + .../yii/framework/views/fi/error500.php | 35 + .../yii/framework/views/fi/error503.php | 31 + .../yii/framework/views/fi/exception.php | 242 + .../yii/framework/views/fi/log-firebug.php | 23 + .../yiisoft/yii/framework/views/fi/log.php | 40 + .../views/fi/profile-callstack-firebug.php | 19 + .../framework/views/fi/profile-callstack.php | 30 + .../views/fi/profile-summary-firebug.php | 22 + .../framework/views/fi/profile-summary.php | 41 + .../yiisoft/yii/framework/views/fr/error.php | 36 + .../yii/framework/views/fr/error400.php | 34 + .../yii/framework/views/fr/error403.php | 33 + .../yii/framework/views/fr/error404.php | 34 + .../yii/framework/views/fr/error500.php | 34 + .../yii/framework/views/fr/error503.php | 32 + .../yii/framework/views/fr/log-firebug.php | 23 + .../yiisoft/yii/framework/views/fr/log.php | 40 + .../views/fr/profile-callstack-firebug.php | 19 + .../framework/views/fr/profile-callstack.php | 30 + .../views/fr/profile-summary-firebug.php | 22 + .../framework/views/fr/profile-summary.php | 41 + .../yiisoft/yii/framework/views/he/error.php | 38 + .../yii/framework/views/he/error400.php | 34 + .../yii/framework/views/he/error403.php | 33 + .../yii/framework/views/he/error404.php | 34 + .../yii/framework/views/he/error500.php | 36 + .../yii/framework/views/he/error503.php | 32 + .../yii/framework/views/he/log-firebug.php | 23 + .../yiisoft/yii/framework/views/he/log.php | 40 + .../views/he/profile-callstack-firebug.php | 19 + .../framework/views/he/profile-callstack.php | 30 + .../views/he/profile-summary-firebug.php | 22 + .../framework/views/he/profile-summary.php | 41 + .../yiisoft/yii/framework/views/hr/error.php | 37 + .../yii/framework/views/hr/error400.php | 34 + .../yii/framework/views/hr/error403.php | 33 + .../yii/framework/views/hr/error404.php | 34 + .../yii/framework/views/hr/error500.php | 35 + .../yii/framework/views/hr/error503.php | 32 + .../yii/framework/views/hr/log-firebug.php | 23 + .../yiisoft/yii/framework/views/hr/log.php | 40 + .../views/hr/profile-callstack-firebug.php | 19 + .../framework/views/hr/profile-callstack.php | 30 + .../views/hr/profile-summary-firebug.php | 22 + .../framework/views/hr/profile-summary.php | 41 + .../yiisoft/yii/framework/views/id/error.php | 37 + .../yii/framework/views/id/error400.php | 33 + .../yii/framework/views/id/error403.php | 32 + .../yii/framework/views/id/error404.php | 33 + .../yii/framework/views/id/error500.php | 35 + .../yii/framework/views/id/error503.php | 31 + .../yii/framework/views/id/log-firebug.php | 23 + .../yiisoft/yii/framework/views/id/log.php | 40 + .../views/id/profile-callstack-firebug.php | 19 + .../framework/views/id/profile-callstack.php | 30 + .../views/id/profile-summary-firebug.php | 22 + .../framework/views/id/profile-summary.php | 41 + .../yiisoft/yii/framework/views/it/error.php | 37 + .../yii/framework/views/it/error400.php | 33 + .../yii/framework/views/it/error403.php | 32 + .../yii/framework/views/it/error404.php | 33 + .../yii/framework/views/it/error500.php | 35 + .../yii/framework/views/it/error503.php | 31 + .../yii/framework/views/it/log-firebug.php | 23 + .../yiisoft/yii/framework/views/it/log.php | 40 + .../views/it/profile-callstack-firebug.php | 19 + .../framework/views/it/profile-callstack.php | 30 + .../views/it/profile-summary-firebug.php | 22 + .../framework/views/it/profile-summary.php | 41 + .../yiisoft/yii/framework/views/ja/error.php | 37 + .../yii/framework/views/ja/error400.php | 33 + .../yii/framework/views/ja/error403.php | 32 + .../yii/framework/views/ja/error404.php | 33 + .../yii/framework/views/ja/error500.php | 35 + .../yii/framework/views/ja/error503.php | 31 + .../yii/framework/views/ja/log-firebug.php | 23 + .../yiisoft/yii/framework/views/ja/log.php | 40 + .../views/ja/profile-callstack-firebug.php | 19 + .../framework/views/ja/profile-callstack.php | 30 + .../views/ja/profile-summary-firebug.php | 22 + .../framework/views/ja/profile-summary.php | 41 + .../yiisoft/yii/framework/views/ko/error.php | 37 + .../yii/framework/views/ko/error400.php | 32 + .../yii/framework/views/ko/error403.php | 32 + .../yii/framework/views/ko/error404.php | 33 + .../yii/framework/views/ko/error500.php | 35 + .../yii/framework/views/ko/error503.php | 31 + .../yii/framework/views/ko/exception.php | 242 + .../yii/framework/views/ko/log-firebug.php | 23 + .../yiisoft/yii/framework/views/ko/log.php | 40 + .../views/ko/profile-callstack-firebug.php | 19 + .../framework/views/ko/profile-callstack.php | 30 + .../views/ko/profile-summary-firebug.php | 22 + .../framework/views/ko/profile-summary.php | 41 + .../yii/framework/views/log-firebug.php | 23 + .../yiisoft/yii/framework/views/log.php | 40 + .../yiisoft/yii/framework/views/lt/error.php | 37 + .../yii/framework/views/lt/error400.php | 33 + .../yii/framework/views/lt/error403.php | 32 + .../yii/framework/views/lt/error404.php | 33 + .../yii/framework/views/lt/error500.php | 35 + .../yii/framework/views/lt/error503.php | 31 + .../yii/framework/views/lt/exception.php | 242 + .../yii/framework/views/lt/log-firebug.php | 23 + .../yiisoft/yii/framework/views/lt/log.php | 40 + .../views/lt/profile-callstack-firebug.php | 19 + .../framework/views/lt/profile-callstack.php | 30 + .../views/lt/profile-summary-firebug.php | 22 + .../framework/views/lt/profile-summary.php | 41 + .../yiisoft/yii/framework/views/lv/error.php | 37 + .../yii/framework/views/lv/error400.php | 33 + .../yii/framework/views/lv/error403.php | 32 + .../yii/framework/views/lv/error404.php | 33 + .../yii/framework/views/lv/error500.php | 35 + .../yii/framework/views/lv/error503.php | 31 + .../yii/framework/views/lv/log-firebug.php | 23 + .../yiisoft/yii/framework/views/lv/log.php | 40 + .../views/lv/profile-callstack-firebug.php | 19 + .../framework/views/lv/profile-callstack.php | 30 + .../views/lv/profile-summary-firebug.php | 22 + .../framework/views/lv/profile-summary.php | 41 + .../yiisoft/yii/framework/views/nl/error.php | 25 + .../yii/framework/views/nl/error400.php | 24 + .../yii/framework/views/nl/error403.php | 24 + .../yii/framework/views/nl/error404.php | 24 + .../yii/framework/views/nl/error500.php | 24 + .../yii/framework/views/nl/error503.php | 24 + .../yii/framework/views/nl/log-firebug.php | 22 + .../yiisoft/yii/framework/views/nl/log.php | 38 + .../views/nl/profile-callstack-firebug.php | 17 + .../framework/views/nl/profile-callstack.php | 29 + .../views/nl/profile-summary-firebug.php | 20 + .../framework/views/nl/profile-summary.php | 41 + .../yiisoft/yii/framework/views/no/error.php | 37 + .../yii/framework/views/no/error400.php | 33 + .../yii/framework/views/no/error403.php | 32 + .../yii/framework/views/no/error404.php | 33 + .../yii/framework/views/no/error500.php | 35 + .../yii/framework/views/no/error503.php | 31 + .../yii/framework/views/no/log-firebug.php | 23 + .../yiisoft/yii/framework/views/no/log.php | 40 + .../views/no/profile-callstack-firebug.php | 19 + .../framework/views/no/profile-callstack.php | 30 + .../views/no/profile-summary-firebug.php | 22 + .../framework/views/no/profile-summary.php | 41 + .../yiisoft/yii/framework/views/pl/error.php | 37 + .../yii/framework/views/pl/error400.php | 33 + .../yii/framework/views/pl/error403.php | 32 + .../yii/framework/views/pl/error404.php | 33 + .../yii/framework/views/pl/error500.php | 35 + .../yii/framework/views/pl/error503.php | 31 + .../yii/framework/views/pl/log-firebug.php | 23 + .../yiisoft/yii/framework/views/pl/log.php | 41 + .../views/pl/profile-callstack-firebug.php | 19 + .../framework/views/pl/profile-callstack.php | 30 + .../views/pl/profile-summary-firebug.php | 22 + .../framework/views/pl/profile-summary.php | 41 + .../views/profile-callstack-firebug.php | 19 + .../yii/framework/views/profile-callstack.php | 30 + .../views/profile-summary-firebug.php | 22 + .../yii/framework/views/profile-summary.php | 41 + .../yiisoft/yii/framework/views/pt/error.php | 37 + .../yii/framework/views/pt/error400.php | 33 + .../yii/framework/views/pt/error403.php | 32 + .../yii/framework/views/pt/error404.php | 33 + .../yii/framework/views/pt/error500.php | 35 + .../yii/framework/views/pt/error503.php | 31 + .../yii/framework/views/pt/log-firebug.php | 23 + .../yiisoft/yii/framework/views/pt/log.php | 40 + .../views/pt/profile-callstack-firebug.php | 19 + .../framework/views/pt/profile-callstack.php | 30 + .../views/pt/profile-summary-firebug.php | 22 + .../framework/views/pt/profile-summary.php | 41 + .../yii/framework/views/pt_br/error.php | 37 + .../yii/framework/views/pt_br/error400.php | 33 + .../yii/framework/views/pt_br/error403.php | 32 + .../yii/framework/views/pt_br/error404.php | 33 + .../yii/framework/views/pt_br/error500.php | 35 + .../yii/framework/views/pt_br/error503.php | 31 + .../yii/framework/views/pt_br/log-firebug.php | 23 + .../yiisoft/yii/framework/views/pt_br/log.php | 40 + .../views/pt_br/profile-callstack-firebug.php | 19 + .../views/pt_br/profile-callstack.php | 30 + .../views/pt_br/profile-summary-firebug.php | 22 + .../framework/views/pt_br/profile-summary.php | 41 + .../yiisoft/yii/framework/views/ro/error.php | 37 + .../yii/framework/views/ro/error400.php | 33 + .../yii/framework/views/ro/error403.php | 32 + .../yii/framework/views/ro/error404.php | 33 + .../yii/framework/views/ro/error500.php | 35 + .../yii/framework/views/ro/error503.php | 31 + .../yii/framework/views/ro/log-firebug.php | 23 + .../yiisoft/yii/framework/views/ro/log.php | 40 + .../views/ro/profile-callstack-firebug.php | 19 + .../framework/views/ro/profile-callstack.php | 30 + .../views/ro/profile-summary-firebug.php | 22 + .../framework/views/ro/profile-summary.php | 41 + .../yiisoft/yii/framework/views/ru/error.php | 37 + .../yii/framework/views/ru/error400.php | 33 + .../yii/framework/views/ru/error403.php | 32 + .../yii/framework/views/ru/error404.php | 33 + .../yii/framework/views/ru/error500.php | 35 + .../yii/framework/views/ru/error503.php | 31 + .../yii/framework/views/ru/log-firebug.php | 23 + .../yiisoft/yii/framework/views/ru/log.php | 40 + .../views/ru/profile-callstack-firebug.php | 19 + .../framework/views/ru/profile-callstack.php | 30 + .../views/ru/profile-summary-firebug.php | 22 + .../framework/views/ru/profile-summary.php | 41 + .../yiisoft/yii/framework/views/sk/error.php | 37 + .../yii/framework/views/sk/error400.php | 33 + .../yii/framework/views/sk/error403.php | 32 + .../yii/framework/views/sk/error404.php | 33 + .../yii/framework/views/sk/error500.php | 35 + .../yii/framework/views/sk/error503.php | 31 + .../yii/framework/views/sk/log-firebug.php | 23 + .../yiisoft/yii/framework/views/sk/log.php | 46 + .../views/sk/profile-callstack-firebug.php | 19 + .../framework/views/sk/profile-callstack.php | 30 + .../views/sk/profile-summary-firebug.php | 22 + .../framework/views/sk/profile-summary.php | 41 + .../yiisoft/yii/framework/views/sv/error.php | 37 + .../yii/framework/views/sv/error400.php | 33 + .../yii/framework/views/sv/error403.php | 33 + .../yii/framework/views/sv/error404.php | 33 + .../yii/framework/views/sv/error500.php | 35 + .../yii/framework/views/sv/error503.php | 31 + .../yii/framework/views/sv/exception.php | 242 + .../yii/framework/views/sv/log-firebug.php | 23 + .../yiisoft/yii/framework/views/sv/log.php | 40 + .../views/sv/profile-callstack-firebug.php | 19 + .../framework/views/sv/profile-callstack.php | 30 + .../views/sv/profile-summary-firebug.php | 22 + .../framework/views/sv/profile-summary.php | 41 + .../yiisoft/yii/framework/views/uk/error.php | 37 + .../yii/framework/views/uk/error400.php | 33 + .../yii/framework/views/uk/error403.php | 32 + .../yii/framework/views/uk/error404.php | 33 + .../yii/framework/views/uk/error500.php | 35 + .../yii/framework/views/uk/error503.php | 31 + .../yii/framework/views/uk/exception.php | 242 + .../yii/framework/views/uk/log-firebug.php | 23 + .../yiisoft/yii/framework/views/uk/log.php | 40 + .../views/uk/profile-callstack-firebug.php | 19 + .../framework/views/uk/profile-callstack.php | 30 + .../views/uk/profile-summary-firebug.php | 22 + .../framework/views/uk/profile-summary.php | 41 + .../yiisoft/yii/framework/views/vi/error.php | 37 + .../yii/framework/views/vi/error400.php | 33 + .../yii/framework/views/vi/error403.php | 32 + .../yii/framework/views/vi/error404.php | 33 + .../yii/framework/views/vi/error500.php | 35 + .../yii/framework/views/vi/error503.php | 31 + .../yii/framework/views/vi/log-firebug.php | 23 + .../yiisoft/yii/framework/views/vi/log.php | 40 + .../views/vi/profile-callstack-firebug.php | 19 + .../framework/views/vi/profile-callstack.php | 30 + .../views/vi/profile-summary-firebug.php | 22 + .../framework/views/vi/profile-summary.php | 41 + .../yii/framework/views/zh_cn/error.php | 37 + .../yii/framework/views/zh_cn/error400.php | 33 + .../yii/framework/views/zh_cn/error403.php | 32 + .../yii/framework/views/zh_cn/error404.php | 33 + .../yii/framework/views/zh_cn/error500.php | 35 + .../yii/framework/views/zh_cn/error503.php | 31 + .../yii/framework/views/zh_cn/log-firebug.php | 23 + .../yiisoft/yii/framework/views/zh_cn/log.php | 40 + .../views/zh_cn/profile-callstack-firebug.php | 19 + .../views/zh_cn/profile-callstack.php | 28 + .../views/zh_cn/profile-summary-firebug.php | 22 + .../framework/views/zh_cn/profile-summary.php | 41 + .../yii/framework/views/zh_tw/error.php | 37 + .../yii/framework/views/zh_tw/error400.php | 33 + .../yii/framework/views/zh_tw/error403.php | 32 + .../yii/framework/views/zh_tw/error404.php | 33 + .../yii/framework/views/zh_tw/error500.php | 35 + .../yii/framework/views/zh_tw/error503.php | 31 + .../yii/framework/views/zh_tw/log-firebug.php | 23 + .../yiisoft/yii/framework/views/zh_tw/log.php | 40 + .../views/zh_tw/profile-callstack-firebug.php | 19 + .../views/zh_tw/profile-callstack.php | 30 + .../views/zh_tw/profile-summary-firebug.php | 22 + .../framework/views/zh_tw/profile-summary.php | 41 + .../yii/framework/web/CActiveDataProvider.php | 232 + .../yii/framework/web/CArrayDataProvider.php | 193 + .../yii/framework/web/CAssetManager.php | 334 + .../yii/framework/web/CBaseController.php | 302 + .../yii/framework/web/CCacheHttpSession.php | 112 + .../yii/framework/web/CClientScript.php | 841 + .../yiisoft/yii/framework/web/CController.php | 1231 ++ .../yii/framework/web/CDataProvider.php | 238 + .../framework/web/CDataProviderIterator.php | 155 + .../yii/framework/web/CDbHttpSession.php | 298 + .../yii/framework/web/CExtController.php | 53 + .../yiisoft/yii/framework/web/CFormModel.php | 78 + .../yiisoft/yii/framework/web/CHttpCookie.php | 94 + .../yii/framework/web/CHttpRequest.php | 1396 ++ .../yii/framework/web/CHttpSession.php | 576 + .../framework/web/CHttpSessionIterator.php | 91 + .../yii/framework/web/COutputEvent.php | 37 + .../yiisoft/yii/framework/web/CPagination.php | 240 + .../yiisoft/yii/framework/web/CSort.php | 472 + .../yii/framework/web/CSqlDataProvider.php | 142 + .../yiisoft/yii/framework/web/CTheme.php | 140 + .../yii/framework/web/CThemeManager.php | 130 + .../yii/framework/web/CUploadedFile.php | 275 + .../yiisoft/yii/framework/web/CUrlManager.php | 850 + .../yii/framework/web/CWebApplication.php | 547 + .../yiisoft/yii/framework/web/CWebModule.php | 202 + .../yii/framework/web/CWidgetFactory.php | 197 + .../yii/framework/web/actions/CAction.php | 111 + .../framework/web/actions/CInlineAction.php | 52 + .../yii/framework/web/actions/CViewAction.php | 167 + .../web/auth/CAccessControlFilter.php | 394 + .../framework/web/auth/CAuthAssignment.php | 106 + .../yii/framework/web/auth/CAuthItem.php | 277 + .../yii/framework/web/auth/CAuthManager.php | 165 + .../framework/web/auth/CBaseUserIdentity.php | 131 + .../yii/framework/web/auth/CDbAuthManager.php | 603 + .../framework/web/auth/CPhpAuthManager.php | 506 + .../yii/framework/web/auth/CUserIdentity.php | 81 + .../yii/framework/web/auth/CWebUser.php | 821 + .../yii/framework/web/auth/schema-mssql.sql | 42 + .../yii/framework/web/auth/schema-mysql.sql | 42 + .../yii/framework/web/auth/schema-oci.sql | 42 + .../yii/framework/web/auth/schema-pgsql.sql | 42 + .../yii/framework/web/auth/schema-sqlite.sql | 42 + .../yii/framework/web/filters/CFilter.php | 74 + .../framework/web/filters/CFilterChain.php | 135 + .../web/filters/CHttpCacheFilter.php | 209 + .../framework/web/filters/CInlineFilter.php | 60 + .../yiisoft/yii/framework/web/form/CForm.php | 614 + .../framework/web/form/CFormButtonElement.php | 138 + .../yii/framework/web/form/CFormElement.php | 167 + .../web/form/CFormElementCollection.php | 111 + .../framework/web/form/CFormInputElement.php | 264 + .../framework/web/form/CFormStringElement.php | 70 + .../yii/framework/web/helpers/CGoogleApi.php | 74 + .../yii/framework/web/helpers/CHtml.php | 2613 +++ .../yii/framework/web/helpers/CJSON.php | 709 + .../yii/framework/web/helpers/CJavaScript.php | 127 + .../web/helpers/CJavaScriptExpression.php | 47 + .../yiisoft/yii/framework/web/js/packages.php | 81 + .../web/js/source/autocomplete/indicator.gif | Bin 0 -> 1553 bytes .../autocomplete/jquery.autocomplete.css | 48 + .../web/js/source/jquery.ajaxqueue.js | 116 + .../web/js/source/jquery.autocomplete.js | 813 + .../framework/web/js/source/jquery.ba-bbq.js | 1378 ++ .../web/js/source/jquery.ba-bbq.min.js | 18 + .../web/js/source/jquery.bgiframe.js | 39 + .../framework/web/js/source/jquery.cookie.js | 92 + .../framework/web/js/source/jquery.history.js | 1 + .../yii/framework/web/js/source/jquery.js | 9472 +++++++++ .../web/js/source/jquery.maskedinput.js | 338 + .../web/js/source/jquery.maskedinput.min.js | 7 + .../web/js/source/jquery.metadata.js | 148 + .../yii/framework/web/js/source/jquery.min.js | 2 + .../web/js/source/jquery.multifile.js | 536 + .../framework/web/js/source/jquery.rating.js | 376 + .../web/js/source/jquery.treeview.async.js | 110 + .../web/js/source/jquery.treeview.edit.js | 37 + .../web/js/source/jquery.treeview.js | 256 + .../yii/framework/web/js/source/jquery.yii.js | 52 + .../web/js/source/jquery.yiiactiveform.js | 432 + .../framework/web/js/source/jquery.yiitab.js | 49 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 86 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 75 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 144 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 99 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 142 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 137 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 140 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 86 bytes .../base/images/ui-icons_222222_256x240.png | Bin 0 -> 3800 bytes .../base/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 3800 bytes .../base/images/ui-icons_454545_256x240.png | Bin 0 -> 3800 bytes .../base/images/ui-icons_888888_256x240.png | Bin 0 -> 3800 bytes .../base/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 3800 bytes .../web/js/source/jui/css/base/jquery-ui.css | 10 + .../jui/css/base/jquery.ui.accordion.css | 5 + .../jui/css/base/jquery.ui.autocomplete.css | 5 + .../source/jui/css/base/jquery.ui.button.css | 5 + .../js/source/jui/css/base/jquery.ui.core.css | 5 + .../jui/css/base/jquery.ui.datepicker.css | 5 + .../source/jui/css/base/jquery.ui.dialog.css | 5 + .../js/source/jui/css/base/jquery.ui.menu.css | 5 + .../jui/css/base/jquery.ui.progressbar.css | 5 + .../jui/css/base/jquery.ui.resizable.css | 5 + .../jui/css/base/jquery.ui.selectable.css | 5 + .../source/jui/css/base/jquery.ui.slider.css | 5 + .../source/jui/css/base/jquery.ui.spinner.css | 5 + .../js/source/jui/css/base/jquery.ui.tabs.css | 5 + .../source/jui/css/base/jquery.ui.theme.css | 5 + .../source/jui/css/base/jquery.ui.tooltip.css | 5 + .../js/source/jui/js/jquery-ui-i18n.min.js | 5 + .../web/js/source/jui/js/jquery-ui.min.js | 6 + .../yii/framework/web/js/source/punycode.js | 510 + .../framework/web/js/source/punycode.min.js | 2 + .../framework/web/js/source/rating/delete.gif | Bin 0 -> 752 bytes .../web/js/source/rating/jquery.rating.css | 12 + .../framework/web/js/source/rating/star.gif | Bin 0 -> 815 bytes .../js/source/treeview/images/ajax-loader.gif | Bin 0 -> 847 bytes .../web/js/source/treeview/images/file.gif | Bin 0 -> 110 bytes .../source/treeview/images/folder-closed.gif | Bin 0 -> 105 bytes .../web/js/source/treeview/images/folder.gif | Bin 0 -> 106 bytes .../web/js/source/treeview/images/minus.gif | Bin 0 -> 837 bytes .../web/js/source/treeview/images/plus.gif | Bin 0 -> 841 bytes .../treeview/images/treeview-black-line.gif | Bin 0 -> 1877 bytes .../source/treeview/images/treeview-black.gif | Bin 0 -> 1216 bytes .../treeview/images/treeview-default-line.gif | Bin 0 -> 1993 bytes .../treeview/images/treeview-default.gif | Bin 0 -> 1222 bytes .../images/treeview-famfamfam-line.gif | Bin 0 -> 807 bytes .../treeview/images/treeview-famfamfam.gif | Bin 0 -> 1280 bytes .../treeview/images/treeview-gray-line.gif | Bin 0 -> 1877 bytes .../source/treeview/images/treeview-gray.gif | Bin 0 -> 1230 bytes .../treeview/images/treeview-red-line.gif | Bin 0 -> 1877 bytes .../source/treeview/images/treeview-red.gif | Bin 0 -> 1230 bytes .../js/source/treeview/jquery.treeview.css | 74 + .../web/js/source/yiitab/jquery.yiitab.css | 58 + .../web/renderers/CPradoViewRenderer.php | 304 + .../framework/web/renderers/CViewRenderer.php | 96 + .../framework/web/services/CWebService.php | 291 + .../web/services/CWebServiceAction.php | 131 + .../framework/web/services/CWsdlGenerator.php | 709 + .../yii/framework/web/widgets/CActiveForm.php | 942 + .../framework/web/widgets/CAutoComplete.php | 294 + .../yii/framework/web/widgets/CClipWidget.php | 52 + .../web/widgets/CContentDecorator.php | 81 + .../framework/web/widgets/CFilterWidget.php | 74 + .../yii/framework/web/widgets/CFlexWidget.php | 121 + .../framework/web/widgets/CHtmlPurifier.php | 130 + .../framework/web/widgets/CInputWidget.php | 80 + .../yii/framework/web/widgets/CMarkdown.php | 117 + .../web/widgets/CMaskedTextField.php | 114 + .../web/widgets/CMultiFileUpload.php | 141 + .../framework/web/widgets/COutputCache.php | 364 + .../web/widgets/COutputProcessor.php | 76 + .../yii/framework/web/widgets/CStarRating.php | 205 + .../yii/framework/web/widgets/CTabView.php | 219 + .../web/widgets/CTextHighlighter.php | 124 + .../yii/framework/web/widgets/CTreeView.php | 245 + .../yii/framework/web/widgets/CWidget.php | 249 + .../web/widgets/captcha/CCaptcha.php | 188 + .../web/widgets/captcha/CCaptchaAction.php | 336 + .../web/widgets/captcha/SpicyRice.md | 11 + .../web/widgets/captcha/SpicyRice.ttf | Bin 0 -> 67244 bytes .../web/widgets/pagers/CBasePager.php | 134 + .../web/widgets/pagers/CLinkPager.php | 229 + .../web/widgets/pagers/CListPager.php | 88 + .../framework/web/widgets/pagers/pager.css | 66 + .../web/widgets/views/flexWidget.php | 99 + .../yiisoft/yii/framework/yii-powered.png | Bin 0 -> 175 bytes .../lib/vendor/yiisoft/yii/framework/yii.php | 27 + .../lib/vendor/yiisoft/yii/framework/yiic | 14 + .../lib/vendor/yiisoft/yii/framework/yiic.bat | 23 + .../lib/vendor/yiisoft/yii/framework/yiic.php | 33 + .../vendor/yiisoft/yii/framework/yiilite.php | 10023 +++++++++ .../lib/vendor/yiisoft/yii/framework/yiit.php | 22 + .../zii/behaviors/CTimestampBehavior.php | 123 + .../framework/zii/widgets/CBaseListView.php | 290 + .../framework/zii/widgets/CBreadcrumbs.php | 132 + .../yii/framework/zii/widgets/CDetailView.php | 255 + .../yii/framework/zii/widgets/CListView.php | 325 + .../yii/framework/zii/widgets/CMenu.php | 323 + .../yii/framework/zii/widgets/CPortlet.php | 125 + .../zii/widgets/assets/detailview/styles.css | 44 + .../zii/widgets/assets/gridview/bg.gif | Bin 0 -> 243 bytes .../zii/widgets/assets/gridview/delete.png | Bin 0 -> 715 bytes .../zii/widgets/assets/gridview/down.gif | Bin 0 -> 55 bytes .../assets/gridview/jquery.yiigridview.js | 472 + .../zii/widgets/assets/gridview/loading.gif | Bin 0 -> 1849 bytes .../zii/widgets/assets/gridview/styles.css | 125 + .../zii/widgets/assets/gridview/up.gif | Bin 0 -> 54 bytes .../zii/widgets/assets/gridview/update.png | Bin 0 -> 713 bytes .../zii/widgets/assets/gridview/view.png | Bin 0 -> 803 bytes .../zii/widgets/assets/listview/down.gif | Bin 0 -> 55 bytes .../assets/listview/jquery.yiilistview.js | 179 + .../zii/widgets/assets/listview/loading.gif | Bin 0 -> 1849 bytes .../zii/widgets/assets/listview/styles.css | 56 + .../zii/widgets/assets/listview/up.gif | Bin 0 -> 54 bytes .../zii/widgets/grid/CButtonColumn.php | 349 + .../zii/widgets/grid/CCheckBoxColumn.php | 248 + .../zii/widgets/grid/CDataColumn.php | 142 + .../zii/widgets/grid/CGridColumn.php | 206 + .../framework/zii/widgets/grid/CGridView.php | 649 + .../zii/widgets/grid/CLinkColumn.php | 111 + .../zii/widgets/jui/CJuiAccordion.php | 95 + .../zii/widgets/jui/CJuiAutoComplete.php | 97 + .../framework/zii/widgets/jui/CJuiButton.php | 173 + .../zii/widgets/jui/CJuiDatePicker.php | 128 + .../framework/zii/widgets/jui/CJuiDialog.php | 85 + .../zii/widgets/jui/CJuiDraggable.php | 78 + .../zii/widgets/jui/CJuiDroppable.php | 78 + .../zii/widgets/jui/CJuiInputWidget.php | 80 + .../zii/widgets/jui/CJuiProgressBar.php | 74 + .../zii/widgets/jui/CJuiResizable.php | 78 + .../zii/widgets/jui/CJuiSelectable.php | 82 + .../framework/zii/widgets/jui/CJuiSlider.php | 76 + .../zii/widgets/jui/CJuiSliderInput.php | 168 + .../zii/widgets/jui/CJuiSortable.php | 86 + .../framework/zii/widgets/jui/CJuiTabs.php | 135 + .../framework/zii/widgets/jui/CJuiWidget.php | 144 + .../yiisoft/yii/requirements/css/main.css | 93 + .../vendor/yiisoft/yii/requirements/index.php | 297 + .../yii/requirements/messages/.htaccess | 1 + .../yii/requirements/messages/ar/yii.php | 42 + .../yii/requirements/messages/bg/yii.php | 31 + .../yii/requirements/messages/ca/yii.php | 41 + .../yii/requirements/messages/config.php | 18 + .../yii/requirements/messages/cs/yii.php | 42 + .../yii/requirements/messages/de/yii.php | 49 + .../yii/requirements/messages/de_de/yii.php | 41 + .../yii/requirements/messages/el/yii.php | 57 + .../yii/requirements/messages/es/yii.php | 42 + .../yii/requirements/messages/fr/yii.php | 42 + .../yii/requirements/messages/he/yii.php | 41 + .../yii/requirements/messages/hu/yii.php | 42 + .../yii/requirements/messages/id/yii.php | 49 + .../yii/requirements/messages/it/yii.php | 41 + .../yii/requirements/messages/ja/yii.php | 59 + .../yii/requirements/messages/nl/yii.php | 41 + .../yii/requirements/messages/no/yii.php | 42 + .../yii/requirements/messages/pl/yii.php | 44 + .../yii/requirements/messages/pt/yii.php | 42 + .../yii/requirements/messages/pt_br/yii.php | 50 + .../yii/requirements/messages/ro/yii.php | 42 + .../yii/requirements/messages/ru/yii.php | 59 + .../yii/requirements/messages/sk/yii.php | 42 + .../yii/requirements/messages/sv/yii.php | 49 + .../yii/requirements/messages/ta_in/yii.php | 46 + .../yii/requirements/messages/uk/yii.php | 50 + .../yii/requirements/messages/vi/yii.php | 41 + .../yii/requirements/messages/zh_cn/yii.php | 41 + .../yii/requirements/messages/zh_tw/yii.php | 41 + .../yiisoft/yii/requirements/views/.htaccess | 1 + .../yii/requirements/views/ar/index.php | 74 + .../yii/requirements/views/bg/index.php | 81 + .../yii/requirements/views/ca/index.php | 74 + .../yii/requirements/views/de/index.php | 76 + .../yii/requirements/views/de_de/index.php | 76 + .../yii/requirements/views/el/index.php | 75 + .../yii/requirements/views/es/index.php | 75 + .../yii/requirements/views/fr/index.php | 75 + .../yii/requirements/views/he/index.php | 76 + .../yiisoft/yii/requirements/views/index.php | 75 + .../yii/requirements/views/it/index.php | 75 + .../yii/requirements/views/ja/index.php | 74 + .../yii/requirements/views/no/index.php | 77 + .../yii/requirements/views/pl/index.php | 76 + .../yii/requirements/views/pt/index.php | 76 + .../yii/requirements/views/pt_br/index.php | 76 + .../yii/requirements/views/ro/index.php | 78 + .../yii/requirements/views/ru/index.php | 75 + .../yii/requirements/views/sk/index.php | 76 + .../yii/requirements/views/sv/index.php | 74 + .../yii/requirements/views/uk/index.php | 75 + .../yii/requirements/views/zh/index.php | 72 + .../yii/requirements/views/zh_cn/index.php | 72 + .../yii/requirements/views/zh_tw/index.php | 72 + .../yiisoft/yii/tests/TestApplication.php | 63 + .../yiisoft/yii/tests/TestHttpRequest.php | 29 + .../yiisoft/yii/tests/assets/.gitignore | 1 + .../vendor/yiisoft/yii/tests/bootstrap.php | 27 + .../base/AnotherNewApplicationComponent.php | 14 + .../framework/base/BehaviorTestController.php | 14 + .../base/CApplicationComponentTest.php | 13 + .../tests/framework/base/CBehaviorTest.php | 95 + .../tests/framework/base/CComponentTest.php | 346 + .../tests/framework/base/CLogRouterTest.php | 54 + .../yii/tests/framework/base/CLoggerTest.php | 49 + .../yii/tests/framework/base/CModelTest.php | 259 + .../yii/tests/framework/base/CModuleTest.php | 123 + .../framework/base/CPropertyValueTest.php | 152 + .../framework/base/CSecurityManagerTest.php | 123 + .../framework/base/CStatePersisterTest.php | 33 + .../base/NewApplicationComponent.php | 13 + .../base/NewBeforeValidateBehavior.php | 8 + .../yii/tests/framework/base/NewBehavior.php | 9 + .../yii/tests/framework/base/NewComponent.php | 46 + .../yii/tests/framework/base/NewFormModel.php | 10 + .../yii/tests/framework/base/NewModel.php | 44 + .../yii/tests/framework/base/NewModule.php | 4 + .../yii/tests/framework/base/TestBehavior.php | 22 + .../caching/CCacheDependencyTest.php | 67 + .../tests/framework/caching/CDbCacheTest.php | 197 + .../caching/CDirectoryCacheDependencyTest.php | 70 + .../caching/CFileCacheDependencyTest.php | 51 + .../framework/caching/CFileCacheTest.php | 53 + .../tests/framework/caching/CMemCacheTest.php | 165 + .../framework/caching/CRedisCacheTest.php | 132 + .../cli/commands/MessageCommandTest.php | 357 + .../collections/CAttributeCollectionTest.php | 126 + .../collections/CConfigurationTest.php | 91 + .../tests/framework/collections/CListTest.php | 215 + .../tests/framework/collections/CMapTest.php | 211 + .../framework/collections/CQueueTest.php | 119 + .../framework/collections/CStackTest.php | 119 + .../framework/collections/CTypedListTest.php | 22 + .../framework/collections/CTypedMapTest.php | 23 + .../framework/collections/data/config.php | 17 + .../tests/framework/db/CDbCommand2Test.php | 451 + .../framework/db/CDbCommandBuilderTest.php | 206 + .../yii/tests/framework/db/CDbCommandTest.php | 255 + .../tests/framework/db/CDbConnectionTest.php | 112 + .../tests/framework/db/CDbDataReaderTest.php | 162 + .../tests/framework/db/CDbTransactionTest.php | 63 + .../framework/db/ar/CActiveRecord2Test.php | 626 + .../db/ar/CActiveRecordEventWrappersTest.php | 560 + .../framework/db/ar/CActiveRecordTest.php | 1503 ++ .../yii/tests/framework/db/data/models.php | 985 + .../yii/tests/framework/db/data/models2.php | 263 + .../yii/tests/framework/db/data/mssql.sql | 392 + .../yii/tests/framework/db/data/mysql.sql | 152 + .../yii/tests/framework/db/data/oci.sql | 321 + .../yii/tests/framework/db/data/postgres.sql | 179 + .../yii/tests/framework/db/data/sqlite.sql | 286 + .../framework/db/schema/CDbCriteriaTest.php | 638 + .../tests/framework/db/schema/CMssqlTest.php | 399 + .../tests/framework/db/schema/CMysql2Test.php | 153 + .../tests/framework/db/schema/CMysqlTest.php | 317 + .../tests/framework/db/schema/COciTest.php | 378 + .../framework/db/schema/CPostgres2Test.php | 126 + .../framework/db/schema/CPostgresTest.php | 274 + .../tests/framework/db/schema/CSqliteTest.php | 336 + .../framework/i18n/CDateFormatterTest.php | 87 + .../yii/tests/framework/i18n/CLocaleTest.php | 247 + .../framework/i18n/CNumberFormatterTest.php | 70 + .../framework/i18n/CPhpMessageSourceTest.php | 18 + .../yii/tests/framework/i18n/YiiTTest.php | 191 + .../yii/tests/framework/i18n/data/en/test.php | 4 + .../yii/tests/framework/i18n/data/ru/test.mo | Bin 0 -> 1422 bytes .../yii/tests/framework/i18n/data/ru/test.php | 15 + .../yii/tests/framework/i18n/data/ru/test.po | 56 + .../tests/framework/i18n/data/zh_cn/test.php | 4 + .../i18n/gettext/CGettextPoFileTest.php | 34 + .../i18n/messages/de_DE/testcategory.php | 5 + .../framework/utils/CDateTimeParserTest.php | 217 + .../tests/framework/utils/CFileHelperTest.php | 163 + .../tests/framework/utils/CFormatterTest.php | 126 + .../utils/CLocalizedFormatterTest.php | 33 + .../validators/CBooleanValidatorTest.php | 104 + .../validators/CCompareValidatorTest.php | 293 + .../validators/CDateValidatorTest.php | 91 + .../validators/CDefaultValueValidatorTest.php | 66 + .../validators/CEmailValidatorTest.php | 75 + .../validators/CExistValidatorTest.php | 142 + .../validators/CFileValidatorTest.php | 38 + .../validators/CNumberValidatorTest.php | 43 + .../validators/CRangeValidatorTest.php | 35 + .../validators/CRequiredValidatorTest.php | 29 + .../validators/CStringValidatorTest.php | 98 + .../validators/CTypeValidatorTest.php | 153 + .../validators/CUniqueValidatorTest.php | 142 + .../validators/CUrlValidatorTest.php | 188 + .../framework/validators/CValidatorTest.php | 66 + .../tests/framework/validators/ModelMock.php | 8 + .../validators/ScenariosTestModel.php | 45 + .../validators/ValidatorTestModel.php | 40 + .../framework/web/CActiveDataProviderTest.php | 58 + .../framework/web/CArrayDataProviderTest.php | 205 + .../tests/framework/web/CAssetManagerTest.php | 42 + .../tests/framework/web/CClientScriptTest.php | 419 + .../tests/framework/web/CControllerTest.php | 187 + .../framework/web/CCookieCollectionTest.php | 106 + .../web/CDataProviderIteratorTest.php | 70 + .../tests/framework/web/CHttpCookieTest.php | 57 + .../tests/framework/web/CHttpRequestTest.php | 273 + .../tests/framework/web/CHttpSessionTest.php | 36 + .../yii/tests/framework/web/CSortTest.php | 84 + .../yii/tests/framework/web/CSortTest.sql | 12 + .../framework/web/CSqlDataProviderTest.php | 39 + .../tests/framework/web/CUploadedFileTest.php | 127 + .../tests/framework/web/CUrlManagerTest.php | 553 + .../yii/tests/framework/web/CUrlRuleTest.php | 80 + .../web/auth/AuthManagerTestBase.php | 243 + .../framework/web/auth/CDbAuthManagerTest.php | 45 + .../web/auth/CPhpAuthManagerTest.php | 29 + .../tests/framework/web/auth/CWebUserTest.php | 77 + .../web/controllers/SoapController.php | 105 + .../framework/web/controllers/admin/index.php | 0 .../framework/web/controllers/article.php | 0 .../tests/framework/web/controllers/home2.php | 0 .../tests/framework/web/controllers/post.php | 0 .../web/helpers/CHtml/providerValue.php | 11 + .../tests/framework/web/helpers/CHtmlTest.php | 1156 + .../tests/framework/web/helpers/CJSONTest.php | 79 + .../web/helpers/CJavaScriptExpressionTest.php | 12 + .../framework/web/helpers/CJavaScriptTest.php | 24 + .../web/services/CWsdlGeneratorTest.php | 156 + .../web/services/SoapInsurerPerson.php | 23 + .../services/SoapInsurerPersonJuristic.php | 46 + .../services/SoapInsurerPersonPhysical.php | 50 + .../web/services/SoapPovCalculationInput.php | 104 + .../web/services/SoapPovCalculationOutput.php | 22 + .../web/services/SoapPovCalculationResult.php | 49 + .../web/widgets/CAutoCompleteTest.php | 35 + .../web/widgets/CMaskedTextFieldTest.php | 35 + .../web/widgets/CMultiFileUploadTest.php | 34 + .../framework/web/widgets/CStarRatingTest.php | 34 + .../zii/behaviors/CTimestampBehaviorTest.php | 163 + .../zii/behaviors/CTimestampBehaviorTest.sql | 11 + .../framework/zii/widgets/CGridViewTest.php | 53 + .../framework/zii/widgets/CListViewTest.php | 37 + .../zii/widgets/grid/CButtonColumnTest.php | 39 + .../zii/widgets/jui/CJuiButtonTest.php | 35 + .../lib/vendor/yiisoft/yii/tests/phpunit.xml | 7 + .../lib/vendor/yiisoft/yii/tests/readme.txt | 13 + .../yiisoft/yii/tests/reports/.gitignore | 1 + .../yiisoft/yii/tests/runtime/.gitignore | 1 + .../lib/vendor/yiisoft/yii/tests/rununit.bat | 1 + .../vendor/yiisoft/yii/tests/travis/README.md | 12 + .../yii/tests/travis/memcache-setup.sh | 16 + .../yiisoft/yii/tests/travis/mysql-setup.sh | 3 + .../yii/tests/travis/postgresql-setup.sh | 5 + src/common/messages/.gitkeep | 0 src/common/models/.gitkeep | 0 src/common/schema/.gitkeep | 0 src/common/widgets/.gitkeep | 0 src/composer.json | 53 + src/composer.lock | 122 + src/composer.phar | Bin 0 -> 808348 bytes src/console/commands/.gitkeep | 0 src/console/components/.gitkeep | 0 src/console/config/console.php | 22 + src/console/config/env.php | 35 + src/console/config/env/dev.php | 35 + src/console/config/env/prod.php | 29 + src/console/data/.gitkeep | 0 src/console/extensions/.gitkeep | 0 src/console/migrations/.gitkeep | 0 src/console/models/.gitkeep | 0 src/frontend/components/.gitkeep | 0 src/frontend/config/env.php | 35 + src/frontend/config/env/dev.php | 35 + src/frontend/config/env/prod.php | 29 + src/frontend/config/frontend.php | 66 + src/frontend/controllers/SiteController.php | 32 + src/frontend/extensions/.gitkeep | 0 src/frontend/helpers/.gitkeep | 0 src/frontend/lib/.gitkeep | 0 src/frontend/models/.gitkeep | 0 src/frontend/modules/.gitkeep | 0 src/frontend/tests/.gitkeep | 0 src/frontend/views/layouts/main.php | 106 + src/frontend/views/site/error.php | 1 + src/frontend/views/site/index.php | 50 + src/frontend/widgets/.gitkeep | 0 src/frontend/www/.htaccess | 550 + .../apple-touch-icon-114x114-precomposed.png | Bin 0 -> 1032 bytes .../apple-touch-icon-57x57-precomposed.png | Bin 0 -> 640 bytes .../apple-touch-icon-72x72-precomposed.png | Bin 0 -> 747 bytes .../www/apple-touch-icon-precomposed.png | Bin 0 -> 640 bytes src/frontend/www/apple-touch-icon.png | Bin 0 -> 640 bytes src/frontend/www/css/bootstrap-responsive.css | 1109 + .../www/css/bootstrap-responsive.min.css | 9 + src/frontend/www/css/bootstrap.css | 6158 ++++++ src/frontend/www/css/bootstrap.min.css | 9 + .../www/css/fonts/Chunkfive-webfont.eot | Bin 0 -> 18610 bytes .../www/css/fonts/Chunkfive-webfont.svg | 121 + .../www/css/fonts/Chunkfive-webfont.ttf | Bin 0 -> 18412 bytes .../www/css/fonts/Chunkfive-webfont.woff | Bin 0 -> 12136 bytes .../www/css/fonts/League_Gothic-webfont.eot | Bin 0 -> 25486 bytes .../www/css/fonts/League_Gothic-webfont.svg | 148 + .../www/css/fonts/League_Gothic-webfont.ttf | Bin 0 -> 25272 bytes .../www/css/fonts/League_Gothic-webfont.woff | Bin 0 -> 15736 bytes src/frontend/www/css/main.css | 22 + src/frontend/www/css/style.css | 767 + src/frontend/www/favicon.ico | Bin 0 -> 1150 bytes src/frontend/www/humans.txt | 20 + src/frontend/www/img/github-logo.png | Bin 0 -> 22194 bytes src/frontend/www/img/html5-logo-165-cut.png | Bin 0 -> 6472 bytes src/frontend/www/index.php | 21 + src/frontend/www/js/libs/bootstrap.js | 2268 ++ src/frontend/www/js/libs/bootstrap.min.js | 6 + src/frontend/www/js/libs/jquery-1.9.1.js | 9597 +++++++++ src/frontend/www/js/libs/jquery-1.9.1.min.js | 5 + .../www/js/libs/modernizr-2.0.6.min.js | 4 + .../libs/modernizr-2.6.2-respond-1.1.0.min.js | 11 + src/frontend/www/js/main.js | 1 + src/frontend/www/js/plugins.js | 24 + src/frontend/www/js/script.js | 222 + src/frontend/www/robots.txt | 3 + src/yiic | 4 + src/yiic.bat | 16 + src/yiic.php | 19 + 3927 files changed, 1033633 insertions(+) create mode 100644 src/.gitignore create mode 100644 src/README.md create mode 100644 src/backend/.htaccess create mode 100644 src/backend/components/.gitkeep create mode 100644 src/backend/config/backend.php create mode 100644 src/backend/config/env.php create mode 100644 src/backend/config/env/dev.php create mode 100644 src/backend/config/env/prod.php create mode 100644 src/backend/controllers/SiteController.php create mode 100644 src/backend/extensions/.gitkeep create mode 100644 src/backend/helpers/.gitkeep create mode 100644 src/backend/lib/.gitkeep create mode 100644 src/backend/models/.gitkeep create mode 100644 src/backend/modules/.gitkeep create mode 100644 src/backend/tests/.gitkeep create mode 100644 src/backend/views/layouts/main.php create mode 100644 src/backend/views/site/error.php create mode 100644 src/backend/views/site/index.php create mode 100644 src/backend/widgets/.gitkeep create mode 100644 src/backend/www/.htaccess create mode 100644 src/backend/www/apple-touch-icon-114x114-precomposed.png create mode 100644 src/backend/www/apple-touch-icon-57x57-precomposed.png create mode 100644 src/backend/www/apple-touch-icon-72x72-precomposed.png create mode 100644 src/backend/www/apple-touch-icon-precomposed.png create mode 100644 src/backend/www/apple-touch-icon.png create mode 100644 src/backend/www/css/bootstrap-responsive.css create mode 100644 src/backend/www/css/bootstrap-responsive.min.css create mode 100644 src/backend/www/css/bootstrap.css create mode 100644 src/backend/www/css/bootstrap.min.css create mode 100644 src/backend/www/css/fonts/Chunkfive-webfont.eot create mode 100644 src/backend/www/css/fonts/Chunkfive-webfont.svg create mode 100644 src/backend/www/css/fonts/Chunkfive-webfont.ttf create mode 100644 src/backend/www/css/fonts/Chunkfive-webfont.woff create mode 100644 src/backend/www/css/fonts/League_Gothic-webfont.eot create mode 100644 src/backend/www/css/fonts/League_Gothic-webfont.svg create mode 100644 src/backend/www/css/fonts/League_Gothic-webfont.ttf create mode 100644 src/backend/www/css/fonts/League_Gothic-webfont.woff create mode 100644 src/backend/www/css/main.css create mode 100644 src/backend/www/css/style.css create mode 100644 src/backend/www/favicon.ico create mode 100644 src/backend/www/humans.txt create mode 100644 src/backend/www/img/github-logo.png create mode 100644 src/backend/www/img/html5-logo-165-cut.png create mode 100644 src/backend/www/index.php create mode 100644 src/backend/www/js/libs/bootstrap.js create mode 100644 src/backend/www/js/libs/bootstrap.min.js create mode 100644 src/backend/www/js/libs/jquery-1.9.1.js create mode 100644 src/backend/www/js/libs/jquery-1.9.1.min.js create mode 100644 src/backend/www/js/libs/modernizr-2.0.6.min.js create mode 100644 src/backend/www/js/libs/modernizr-2.6.2-respond-1.1.0.min.js create mode 100644 src/backend/www/js/main.js create mode 100644 src/backend/www/js/plugins.js create mode 100644 src/backend/www/js/script.js create mode 100644 src/backend/www/robots.txt create mode 100644 src/common/.htaccess create mode 100644 src/common/components/.gitkeep create mode 100644 src/common/config/env.php create mode 100644 src/common/config/env/dev.php create mode 100644 src/common/config/env/prod.php create mode 100644 src/common/config/main.php create mode 100644 src/common/config/test.php create mode 100644 src/common/data/.gitkeep create mode 100644 src/common/data/testdrive.db create mode 100644 src/common/extensions/.gitkeep create mode 100644 src/common/extensions/components/EActiveRecord.php create mode 100644 src/common/extensions/components/EController.php create mode 100644 src/common/extensions/components/EWebApplication.php create mode 100644 src/common/helpers/.gitkeep create mode 100644 src/common/lib/Yiinitializr/CHANGELOG create mode 100644 src/common/lib/Yiinitializr/Cli/Console.php create mode 100644 src/common/lib/Yiinitializr/Cli/Daemon.php create mode 100644 src/common/lib/Yiinitializr/Composer/Callback.php create mode 100644 src/common/lib/Yiinitializr/Helpers/ArrayX.php create mode 100644 src/common/lib/Yiinitializr/Helpers/Config.php create mode 100644 src/common/lib/Yiinitializr/Helpers/Initializer.php create mode 100644 src/common/lib/Yiinitializr/LICENSE create mode 100644 src/common/lib/Yiinitializr/README.md create mode 100644 src/common/lib/Yiinitializr/composer.json create mode 100644 src/common/lib/Yiinitializr/config/console.php create mode 100644 src/common/lib/Yiinitializr/config/env.lock create mode 100644 src/common/lib/Yiinitializr/config/settings.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/.gitignore create mode 100644 src/common/lib/vendor/2amigos/yiistrap/README.md create mode 100644 src/common/lib/vendor/2amigos/yiistrap/TODO.md create mode 100644 src/common/lib/vendor/2amigos/yiistrap/assets/css/bootstrap-responsive.css create mode 100644 src/common/lib/vendor/2amigos/yiistrap/assets/css/bootstrap-responsive.min.css create mode 100644 src/common/lib/vendor/2amigos/yiistrap/assets/css/bootstrap.css create mode 100644 src/common/lib/vendor/2amigos/yiistrap/assets/css/bootstrap.min.css create mode 100644 src/common/lib/vendor/2amigos/yiistrap/assets/img/glyphicons-halflings-white.png create mode 100644 src/common/lib/vendor/2amigos/yiistrap/assets/img/glyphicons-halflings.png create mode 100644 src/common/lib/vendor/2amigos/yiistrap/assets/js/bootstrap.js create mode 100644 src/common/lib/vendor/2amigos/yiistrap/assets/js/bootstrap.min.js create mode 100644 src/common/lib/vendor/2amigos/yiistrap/behaviors/TbWidget.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/components/TbApi.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/composer.json create mode 100644 src/common/lib/vendor/2amigos/yiistrap/helpers/TbHtml.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbActiveForm.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbAffix.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbAlert.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbBreadcrumb.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbButtonColumn.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbCollapse.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbDataColumn.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbGridView.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbHeroUnit.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbListView.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbModal.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbNav.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbNavbar.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbPager.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbScrollspy.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbTabs.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbThumbnails.php create mode 100644 src/common/lib/vendor/2amigos/yiistrap/widgets/TbTypeAhead.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/.gitignore create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/README.md create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/YiiWheels.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/README.md create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/css/bootstrap-image-gallery.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/css/bootstrap-image-gallery.min.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/css/bootstrap-notify.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/img/loading.gif create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/bootstrap-bootbox.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/bootstrap-image-gallery.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/bootstrap-image-gallery.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/bootstrap-notify.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/declarative.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/jquery.mousewheel.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/json2.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/moment.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/require.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/spin.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/assets/js/underscore.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/behaviors/WhPlugin.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/composer.json create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/helpers/WhHtml.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/WhAceEditor.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/ace.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/ext-searchbox.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/ext-spellcheck.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/ext-static_highlight.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/ext-textarea.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/keybinding-emacs.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/keybinding-vim.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-abap.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-asciidoc.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-c9search.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-c_cpp.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-clojure.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-coffee.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-coldfusion.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-csharp.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-css.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-curly.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-dart.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-diff.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-django.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-dot.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-glsl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-golang.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-groovy.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-haml.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-haxe.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-html.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-jade.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-java.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-javascript.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-json.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-jsp.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-jsx.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-latex.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-less.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-liquid.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-lisp.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-livescript.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-lua.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-luapage.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-lucene.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-makefile.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-markdown.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-objectivec.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-ocaml.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-pascal.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-perl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-pgsql.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-php.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-powershell.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-python.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-r.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-rdoc.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-rhtml.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-ruby.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-sass.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-scad.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-scala.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-scheme.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-scss.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-sh.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-sql.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-stylus.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-svg.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-tcl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-tex.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-text.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-textile.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-tm_snippet.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-tmsnippet.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-typescript.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-vbscript.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-xml.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-xquery.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/mode-yaml.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-ambiance.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-chaos.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-chrome.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-clouds.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-clouds_midnight.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-cobalt.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-crimson_editor.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-dawn.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-dreamweaver.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-eclipse.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-github.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-idle_fingers.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-kr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-merbivore.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-merbivore_soft.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-mono_industrial.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-monokai.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-pastel_on_dark.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-solarized_dark.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-solarized_light.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-textmate.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-tomorrow.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-tomorrow_night.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-tomorrow_night_blue.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-tomorrow_night_bright.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-tomorrow_night_eighties.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-twilight.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-vibrant_ink.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/theme-xcode.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/worker-coffee.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/worker-css.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/worker-javascript.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/worker-json.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/worker-php.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/ace/assets/js/worker-xquery.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/WhDatePicker.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/build/build.less create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/build/build_standalone.less create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/css/datepicker.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/bootstrap-datepicker.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.bg.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.ca.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.cs.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.da.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.de.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.el.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.es.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.fi.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.fr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.he.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.hr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.hu.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.id.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.is.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.it.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.ja.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.kr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.lt.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.lv.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.ms.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.nb.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.nl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.pl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.pt-BR.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.pt.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.ro.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.rs-latin.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.rs.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.ru.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.sk.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.sl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.sv.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.sw.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.th.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.tr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.uk.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.zh-CN.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/js/locales/bootstrap-datepicker.zh-TW.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/datepicker/assets/less/datepicker.less create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/daterangepicker/WhDateRangePicker.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/daterangepicker/assets/css/daterangepicker.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/daterangepicker/assets/js/daterangepicker.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/detail/WhDetailView.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/WhBasicFileUpload.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/WhFileUpload.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/css/jquery.fileupload-ui.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/img/loading.gif create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/img/progressbar.gif create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/canvas-to-blob.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/cors/jquery.postmessage-transport.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/cors/jquery.xdr-transport.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/jquery.fileupload-fp.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/jquery.fileupload-ip.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/jquery.fileupload-locale.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/jquery.fileupload-ui.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/jquery.fileupload.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/jquery.iframe-transport.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/load-image.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/main.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/tmpl.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/vendor/jquery-ui-1.9.1.custom.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/vendor/jquery.ui.widget.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/download.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/form.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/upload.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/WhFineUploader.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/css/fineuploader.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/img/loading.gif create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/img/processing.gif create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/js/jquery.fineuploader-3.2.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/js/jquery.fineuploader-3.2.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/form/WhActiveForm.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/google/WhVisualizationChart.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/grid/WhRelationalColumn.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/WhHighCharts.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/mootools-adapter.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/mootools-adapter.src.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/prototype-adapter.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/prototype-adapter.src.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts-more.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts.src.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/canvas-tools.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/canvas-tools.src.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/exporting.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/exporting.src.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/dark-blue.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/dark-green.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/gray.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/grid.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/skies.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/WhHtml5Editor.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/css/bootstrap-wysihtml5.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/css/wysiwyg-color.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/bootstrap-wysihtml5.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.bg-BG.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.de-DE.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.es-ES.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.fr-FR.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.fr-NL.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.hu-HU.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.pt-BR.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.sv-SE.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/wysihtml5-0.3.0.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/maskmoney/WhMaskMoney.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/maskmoney/assets/js/jquery.maskmoney.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/modal/WhModal.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/modal/assets/css/bootstrap-modal.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/modal/assets/img/ajax-loader.gif create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/modal/assets/js/bootstrap-modal.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/modal/assets/js/bootstrap-modalmanager.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/multiselect/WhMultiSelect.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/multiselect/assets/css/bootstrap-multiselect.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/multiselect/assets/js/bootstrap-multiselect.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/rangeslider/WhRangeSlider.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/rangeslider/assets/css/classic.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/rangeslider/assets/css/iThing.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/rangeslider/assets/css/icons-classic/label.png create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/rangeslider/assets/css/icons-classic/resultset_next.png create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/rangeslider/assets/css/icons-classic/resultset_previous.png create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/rangeslider/assets/js/jQAllRangeSliders-min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/rangeslider/assets/js/jQAllRangeSliders-withRuler-min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/WhRedactor.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/css/redactor.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/ar.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/az.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/ba.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/bg.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/by.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/ca.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/cs.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/da.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/de.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/el.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/eo.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/es.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/es_ar.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/fa.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/fi.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/fr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/he.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/hr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/hu.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/id.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/it.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/ja.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/ko.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/lt.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/lv.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/mk.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/nl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/no_NB.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/pl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/pt_br.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/ro.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/ru.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/sk.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/sl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/sq.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/sr-cir.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/sr-lat.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/sv.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/tr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/ua.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/vi.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/zh_cn.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/langs/zh_tw.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/plugins/clips/clips.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/plugins/clips/clips.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/plugins/fullscreen/fullscreen.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/redactor.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/assets/js/redactor.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/redactor/license.md create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/select2/WhSelect2.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/select2/assets/css/select2.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/select2/assets/img/select2-spinner.gif create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/select2/assets/img/select2.png create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/select2/assets/img/select2x2.png create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/select2/assets/js/locale/select2_locale_it.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/select2/assets/js/select2.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/sparklines/WhSparklines.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/sparklines/assets/js/jquery.sparkline.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/sparklines/assets/js/jquery.sparkline.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/WhTimeAgo.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/jquery.timeago.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/README.md create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.ar.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.bg.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.bs.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.ca.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.cy.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.cz.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.da.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.de.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.el.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.en-short.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.en.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.es.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.fa.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.fi.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.fr-short.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.fr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.he.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.hr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.hu.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.hy.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.id.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.it.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.ja.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.ko.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.mk.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.nl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.no.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.pl.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.pt-br.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.pt.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.ro.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.ru.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.sk.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.sv.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.th.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.tr.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.uk.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.uz.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.zh-CN.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timeago/assets/js/locales/jquery.timeago.zh-TW.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timepicker/WhTimePicker.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timepicker/assets/css/bootstrap-timepicker.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timepicker/assets/css/bootstrap-timepicker.min.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timepicker/assets/js/bootstrap-timepicker.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timepicker/assets/js/bootstrap-timepicker.min.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/timepicker/assets/less/timepicker.less create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/toggle/WhToggleAction.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/toggle/WhToggleButton.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/toggle/WhToggleColumn.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/toggle/assets/css/bootstrap-toggle-buttons.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/toggle/assets/js/jquery.toggle.buttons.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/typeahead/WhTypeAhead.php create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/typeahead/assets/css/typeahead.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/typeahead/assets/css/typeahead.min.css create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/typeahead/assets/js/typeahead.js create mode 100644 src/common/lib/vendor/2amigos/yiiwheels/widgets/typeahead/assets/js/typeahead.min.js create mode 100644 src/common/lib/vendor/autoload.php create mode 100644 src/common/lib/vendor/composer/ClassLoader.php create mode 100644 src/common/lib/vendor/composer/autoload_classmap.php create mode 100644 src/common/lib/vendor/composer/autoload_namespaces.php create mode 100644 src/common/lib/vendor/composer/autoload_real.php create mode 100644 src/common/lib/vendor/composer/installed.json create mode 100644 src/common/lib/vendor/yiisoft/yii/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/.mailmap create mode 100644 src/common/lib/vendor/yiisoft/yii/.travis.yml create mode 100644 src/common/lib/vendor/yiisoft/yii/CHANGELOG create mode 100644 src/common/lib/vendor/yiisoft/yii/CONTRIBUTING.md create mode 100644 src/common/lib/vendor/yiisoft/yii/LICENSE create mode 100644 src/common/lib/vendor/yiisoft/yii/README create mode 100644 src/common/lib/vendor/yiisoft/yii/README.md create mode 100644 src/common/lib/vendor/yiisoft/yii/UPGRADE create mode 100644 src/common/lib/vendor/yiisoft/yii/build/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/build/build create mode 100644 src/common/lib/vendor/yiisoft/yii/build/build.bat create mode 100644 src/common/lib/vendor/yiisoft/yii/build/build.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/ApiCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/AutoloadCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/BlogLatexCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/CheckBomCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/CldrCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/GuideLatexCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/LiteCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/TranslationsCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/Utf8Command.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/ApiModel.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/assets/css/api.css create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/assets/css/style.css create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/assets/js/jquery.js create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/layouts/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/chmContents.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/chmIndex.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/chmProject.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/class.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/classSummary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/eventDetails.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/eventSummary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/methodDetails.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/methodSummary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/propertyDetails.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/propertySummary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/seeAlso.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/api/views/sourceCode.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/blog/blog.tex create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/blog/license.tex create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/blog/preamble.tex create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/blog/title.tex create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/guide/guide.tex create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/guide/license.tex create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/guide/preamble.tex create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/guide/title.tex create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/css/bg.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/css/form.css create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/css/main.css create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/components/MainMenu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/components/UserIdentity.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/components/views/mainMenu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/config/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/controllers/PostController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/controllers/SiteController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/data/source.db create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/models/LoginForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/models/Post.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/views/layouts/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/views/post/create.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/views/post/list.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/views/post/show.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/views/post/update.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/views/site/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/lite/protected/views/site/login.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/markdown/Markdown.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/markdown/MarkdownHtml2Tex.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/markdown/MarkdownParser.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/commands/translations/report_html.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/generate_accessors_phpdoc.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/tasks/YiiInitTask.php create mode 100644 src/common/lib/vendor/yiisoft/yii/build/tasks/YiiPearTask.php create mode 100644 src/common/lib/vendor/yiisoft/yii/composer.json create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/assets/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/css/bg.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/css/form.css create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/css/ie.css create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/css/main.css create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/css/print.css create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/css/screen.css create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/index-test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/components/Controller.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/components/RecentComments.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/components/TagCloud.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/components/UserIdentity.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/components/UserMenu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/components/views/recentComments.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/components/views/userMenu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/config/console.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/config/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/config/params.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/config/test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/controllers/CommentController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/controllers/PostController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/controllers/SiteController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/data/blog-test.db create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/data/blog.db create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/data/dbgen.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/data/schema.mysql.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/data/schema.sqlite.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/models/Comment.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/models/ContactForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/models/LoginForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/models/Lookup.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/models/Post.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/models/Tag.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/models/User.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/runtime/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/WebTestCase.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/bootstrap.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/fixtures/tbl_comment.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/fixtures/tbl_lookup.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/fixtures/tbl_post.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/fixtures/tbl_tag.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/fixtures/tbl_user.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/functional/CommentTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/functional/PostTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/functional/SiteTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/phpunit.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/readme.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/unit/CommentTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/unit/LookupTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/unit/PostTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/unit/TagTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/tests/unit/UserTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/comment/_form.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/comment/_view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/comment/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/comment/update.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/layouts/column1.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/layouts/column2.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/layouts/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/post/_comments.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/post/_form.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/post/_view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/post/admin.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/post/create.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/post/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/post/update.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/post/view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/site/contact.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/site/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/site/login.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/views/site/pages/about.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/yiic create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/yiic.bat create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/protected/yiic.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/blog/themes/classic/views/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/assets/empty create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/config/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/controllers/GameController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/controllers/words.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/runtime/empty create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/views/game/guess.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/views/game/lose.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/views/game/play.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/views/game/win.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/hangman/protected/views/layouts/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/helloworld/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/helloworld/protected/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/helloworld/protected/controllers/SiteController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/.actionScriptProperties create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/.flexProperties create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/.project create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/.settings/com.adobe.flexbuilder.project.prefs create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/.settings/org.eclipse.core.resources.prefs create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/bin/AC_OETags.js create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/bin/history/history.css create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/bin/history/history.js create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/bin/history/historyFrame.html create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/bin/phonebook.html create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/bin/phonebook.swf create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/bin/playerProductInstall.swf create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/html-template/AC_OETags.js create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/html-template/history/history.css create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/html-template/history/history.js create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/html-template/history/historyFrame.html create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/html-template/index.template.html create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/html-template/playerProductInstall.swf create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/flex/phonebook.mxml create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/protected/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/protected/components/UserIdentity.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/protected/config/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/protected/controllers/SiteController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/protected/data/phonebook.db create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/protected/data/schema.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/protected/models/Contact.php create mode 100644 src/common/lib/vendor/yiisoft/yii/demos/phonebook/protected/views/site/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/README.md create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ar/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/comment.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/comment.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/final.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/final.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/portlet.comments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/portlet.menu.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/portlet.tags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/post.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/post.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/post.display.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/post.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/prototype.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/prototype.database.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/prototype.scaffold.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/prototype.summary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/start.design.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/es/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/final.deployment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/final.future.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/final.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/final.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/comment.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/comment.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/final.deployment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/final.future.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/final.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/final.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/portlet.comments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/portlet.menu.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/portlet.tags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/post.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/post.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/post.display.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/post.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/prototype.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/prototype.database.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/prototype.scaffold.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/prototype.summary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/start.design.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/id/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/images/schema.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/images/schema.vsd create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/comment.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/comment.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/final.deployment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/final.future.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/final.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/final.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/portlet.comments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/portlet.menu.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/portlet.tags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/post.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/post.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/post.display.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/post.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/prototype.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/prototype.database.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/prototype.scaffold.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/prototype.summary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/start.design.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ja/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/comment.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/comment.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/final.deployment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/final.future.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/final.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/final.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/portlet.comments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/portlet.menu.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/portlet.tags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/post.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/post.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/post.display.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/post.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/prototype.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/prototype.database.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/prototype.scaffold.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/prototype.summary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/start.design.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pl/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/portlet.comments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/portlet.menu.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/portlet.tags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/post.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/post.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/post.display.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/post.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/prototype.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/prototype.database.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/prototype.scaffold.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/prototype.summary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt_br/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt_br/comment.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt_br/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt_br/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt_br/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/pt_br/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/comment.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/comment.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/final.deployment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/final.future.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/final.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/final.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/portlet.comments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/portlet.menu.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/portlet.tags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/post.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/post.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/post.display.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/post.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/prototype.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/prototype.database.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/prototype.scaffold.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/prototype.summary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/start.design.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/ru/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/start.design.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/comment.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/comment.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/final.deployment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/final.future.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/final.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/final.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/portlet.comments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/portlet.menu.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/portlet.tags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/post.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/post.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/post.display.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/post.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/prototype.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/prototype.database.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/prototype.scaffold.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/prototype.summary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/start.design.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/uk/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/comment.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/comment.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/comment.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/final.deployment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/final.future.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/final.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/final.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/portlet.comments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/portlet.menu.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/portlet.tags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/post.admin.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/post.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/post.display.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/post.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/prototype.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/prototype.database.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/prototype.scaffold.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/prototype.summary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/start.design.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/start.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/start.requirements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/start.testdrive.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/blog/zh_cn/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/css/info.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/css/main.css create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/css/note.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/css/rtl.css create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/css/tip.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/de/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/es/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/fr/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/he/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/hu/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/id/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/er.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/er.vsd create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/first-app1.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/first-app2.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/first-app3.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/first-app4.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/first-app5.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/first-app6.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/first-app7.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/flow.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/flow.vsd create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/gii-crud.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/gii-model.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/has_many_through.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/has_one_through.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/login1.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/login2.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/structure.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/structure.vsd create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/images/through_self.png create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/it/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ja/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/nl/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/nl/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/nl/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/nl/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/nl/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/nl/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/no/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/no/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/no/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/no/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/no/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/no/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pl/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/pt_br/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ro/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/ru/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/sv/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/database.migration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/database.query-builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/quickstart.apache-nginx-config.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/quickstart.first-app-yiic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/test.functional.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/test.unit.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.console.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.prado.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/uk/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/vi/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/vi/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/vi/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/vi/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/vi/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/vi/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_cn/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.application.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.best-practices.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.component.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.controller.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.convention.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.entry.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.module.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.mvc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.namespace.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/basics.workflow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/caching.data.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/caching.dynamic.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/caching.fragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/caching.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/caching.page.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/changes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/database.ar.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/database.arr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/database.dao.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/database.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/extension.create.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/extension.integration.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/extension.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/extension.use.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/form.action.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/form.builder.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/form.model.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/form.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/form.table.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/form.view.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/index.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/quickstart.first-app.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/quickstart.installation.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/quickstart.what-is-yii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/test.fixture.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/test.overview.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/toc.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.auth.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.error.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.gii.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.i18n.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.logging.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.performance.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.security.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.theming.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.url.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/topics.webservice.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/guide/zh_tw/upgrade.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/components/MarkdownParser.php create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/config/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/controllers/BlogController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/controllers/GuideController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/runtime/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/views/blog/view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/views/guide/view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/docs/viewer/views/layouts/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/YiiBase.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CApplication.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CApplicationComponent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CBehavior.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CComponent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CErrorEvent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CErrorHandler.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CException.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CExceptionEvent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CHttpException.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CModel.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CModelBehavior.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CModelEvent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CModule.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CSecurityManager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/CStatePersister.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/base/interfaces.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CApcCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CDbCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CDummyCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CEAcceleratorCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CFileCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CMemCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CRedisCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CWinCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CXCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/CZendDataCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/dependencies/CCacheDependency.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/dependencies/CChainedCacheDependency.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/dependencies/CDbCacheDependency.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/dependencies/CDirectoryCacheDependency.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/dependencies/CExpressionDependency.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/dependencies/CFileCacheDependency.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/caching/dependencies/CGlobalStateCacheDependency.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/MessageCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/MigrateCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/ShellCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/WebAppCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/shell/ControllerCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/shell/CrudCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/shell/FormCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/shell/HelpCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/shell/ModelCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/commands/shell/ModuleCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/runtime/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/controller/controller.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/controller/view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/_form.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/_search.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/_view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/admin.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/controller.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/create.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/update.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/crud/view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/form/action.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/form/form.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/model/fixture.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/model/model.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/model/test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/module/components/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/module/controllers/DefaultController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/module/messages/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/module/models/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/module/module.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/module/views/default/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/shell/module/views/layouts/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/assets/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/assets/git-gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/assets/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/css/bg.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/css/form.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/css/ie.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/css/main.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/css/print.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/css/screen.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/hg-hgignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/images/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/images/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/images/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/index-test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/commands/shell/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/commands/shell/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/commands/shell/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/components/Controller.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/components/UserIdentity.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/config/console.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/config/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/config/test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/controllers/SiteController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/data/schema.mysql.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/data/schema.sqlite.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/data/testdrive.db create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/extensions/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/extensions/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/extensions/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/messages/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/messages/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/messages/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/migrations/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/migrations/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/migrations/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/models/ContactForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/models/LoginForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/runtime/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/runtime/git-gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/runtime/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/WebTestCase.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/bootstrap.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/fixtures/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/fixtures/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/fixtures/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/functional/SiteTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/phpunit.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/report/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/report/git-gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/report/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/unit/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/unit/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/tests/unit/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/vendor/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/vendor/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/vendor/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/views/layouts/column1.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/views/layouts/column2.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/views/layouts/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/views/site/contact.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/views/site/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/views/site/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/views/site/login.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/views/site/pages/about.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/yiic create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/yiic.bat create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/protected/yiic.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/layouts/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/layouts/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/layouts/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/site/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/site/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/site/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/system/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/system/git-gitkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/cli/views/webapp/themes/classic/views/system/hg-hgkeep create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CAttributeCollection.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CConfiguration.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CList.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CListIterator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CMap.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CMapIterator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CQueue.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CQueueIterator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CStack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CStackIterator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CTypedList.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/collections/CTypedMap.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/console/CConsoleApplication.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/console/CConsoleCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/console/CConsoleCommandBehavior.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/console/CConsoleCommandEvent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/console/CConsoleCommandRunner.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/console/CHelpCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/CDbCommand.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/CDbConnection.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/CDbDataReader.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/CDbException.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/CDbMigration.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/CDbTransaction.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/ar/CActiveFinder.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/ar/CActiveRecord.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/ar/CActiveRecordBehavior.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/CDbColumnSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/CDbCommandBuilder.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/CDbCriteria.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/CDbExpression.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/CDbSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/CDbTableSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mssql/CMssqlColumnSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mssql/CMssqlCommandBuilder.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mssql/CMssqlPdoAdapter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mssql/CMssqlSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mssql/CMssqlSqlsrvPdoAdapter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mssql/CMssqlTableSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mysql/CMysqlColumnSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mysql/CMysqlCommandBuilder.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mysql/CMysqlSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/mysql/CMysqlTableSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/oci/COciColumnSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/oci/COciCommandBuilder.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/oci/COciSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/oci/COciTableSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/pgsql/CPgsqlColumnSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/pgsql/CPgsqlCommandBuilder.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/pgsql/CPgsqlSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/pgsql/CPgsqlTableSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/sqlite/CSqliteColumnSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/sqlite/CSqliteCommandBuilder.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/db/schema/sqlite/CSqliteSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/CCodeFile.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/CCodeForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/CCodeGenerator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/CCodeModel.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/GiiModule.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/css/ie.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/css/main.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/css/print.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/css/screen.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/images/logo.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/blank.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_close.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_loading.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_nav_left.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_nav_right.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_shadow_e.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_shadow_n.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_shadow_ne.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_shadow_nw.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_shadow_s.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_shadow_se.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_shadow_sw.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_shadow_w.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_title_left.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_title_main.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_title_over.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancy_title_right.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancybox-x.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancybox-y.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/fancybox.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/jquery.fancybox-1.3.1.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/fancybox/jquery.fancybox-1.3.1.pack.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/main.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/assets/js/tooltip.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Engine/native.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Engine/shell.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Engine/string.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Engine/xdiff.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Mapped.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Renderer.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Renderer/context.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Renderer/inline.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/Renderer/unified.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff/ThreeWay.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/Pear/Text/Diff3.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/TextDiff.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/components/UserIdentity.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/controllers/DefaultController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/controller/ControllerCode.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/controller/ControllerGenerator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/controller/templates/default/controller.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/controller/templates/default/view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/controller/views/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/CrudCode.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/CrudGenerator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/_form.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/_search.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/_view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/admin.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/controller.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/create.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/update.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/templates/default/view.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/crud/views/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/form/FormCode.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/form/FormGenerator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/form/templates/default/action.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/form/templates/default/form.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/form/views/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/model/ModelCode.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/model/ModelGenerator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/model/templates/default/model.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/model/views/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/ModuleCode.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/ModuleGenerator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/templates/default/components/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/templates/default/controllers/DefaultController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/templates/default/messages/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/templates/default/models/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/templates/default/module.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/templates/default/views/default/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/templates/default/views/layouts/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/generators/module/views/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/models/LoginForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/common/code.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/common/diff.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/common/generator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/default/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/default/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/default/login.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/layouts/column1.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/layouts/generator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/gii/views/layouts/main.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/CChoiceFormat.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/CDateFormatter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/CDbMessageSource.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/CGettextMessageSource.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/CLocale.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/CMessageSource.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/CNumberFormatter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/CPhpMessageSource.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/README.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/aa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/aa_dj.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/aa_er.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/aa_et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/af.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/af_na.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/af_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/agq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/agq_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ak.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ak_gh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/am.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/am_et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_001.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_ae.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_bh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_dz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_eg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_iq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_jo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_kw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_lb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_ly.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_ma.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_om.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_qa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_sa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_sd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_sy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_tn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ar_ye.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/as.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/as_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/asa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/asa_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az_arab.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az_arab_ir.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az_az.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az_cyrl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az_cyrl_az.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az_ir.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/az_latn_az.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bas.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bas_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/be.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/be_by.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bem.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bem_zm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bez.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bez_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bg_bg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bm_ml.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bn_bd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bn_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bo_cn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bo_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/br.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/br_fr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/brx.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/brx_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/bs_ba.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/byn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/byn_er.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ca.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ca_es.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/cch.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/cch_ng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/cgg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/cgg_ug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/chr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/chr_us.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/cs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/cs_cz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/cy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/cy_gb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/da.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/da_dk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dav.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dav_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/de.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/de_at.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/de_be.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/de_ch.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/de_de.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/de_li.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/de_lu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dje.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dje_ne.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dua.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dua_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dv_mv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dyo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dyo_sn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/dz_bt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ebu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ebu_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ee.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ee_gh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ee_tg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/el.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/el_cy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/el_gr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/el_polyton.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_as.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_au.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_bb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_be.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_bm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_bw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_bz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_ca.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_dsrt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_dsrt_us.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_gb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_gu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_gy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_hk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_ie.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_jm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_mh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_mp.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_mt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_mu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_na.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_nz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_ph.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_pk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_sg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_shaw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_tt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_um.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_us.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_us_posix.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_vi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_zw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/en_zz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/eo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_419.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_ar.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_bo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_cl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_co.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_cr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_do.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_ec.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_es.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_gq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_gt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_hn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_mx.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_ni.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_pa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_pe.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_pr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_py.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_sv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_us.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_uy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/es_ve.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/et_ee.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/eu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/eu_es.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ewo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ewo_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fa_af.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fa_ir.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ff.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ff_sn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fi_fi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fil.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fil_ph.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fo_fo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_be.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_bf.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_bi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_bj.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_bl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_ca.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_cd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_cf.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_cg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_ch.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_ci.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_dj.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_fr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_ga.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_gf.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_gn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_gp.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_gq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_km.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_lu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_mc.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_mf.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_mg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_ml.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_mq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_ne.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_re.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_rw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_sn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_td.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_tg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fr_yt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fur.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/fur_it.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ga.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ga_ie.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gaa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gaa_gh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gd_gb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gez.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gez_er.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gez_et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gl_es.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gsw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gsw_ch.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gu_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/guz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/guz_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/gv_gb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_arab.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_arab_ng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_arab_sd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_gh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_latn_gh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_latn_ne.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_latn_ng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_ne.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_ng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ha_sd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/haw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/haw_us.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/he.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/he_il.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/hi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/hi_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/hr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/hr_hr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/hu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/hu_hu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/hy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/hy_am.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ia.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/id.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/id_id.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ig.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ig_ng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ii_cn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/is.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/is_is.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/it.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/it_ch.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/it_it.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/iu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/iw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ja.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ja_jp.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/jmc.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/jmc_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ka.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ka_ge.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kab.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kab_dz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kaj.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kaj_ng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kam.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kam_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kcg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kcg_ng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kde.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kde_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kea.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kea_cv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kfo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kfo_ci.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/khq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/khq_ml.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ki.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ki_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kk_cyrl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kk_cyrl_kz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kk_kz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kl_gl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kln.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kln_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/km.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/km_kh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kn_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ko.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ko_kr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kok.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kok_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kpe.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kpe_gn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kpe_lr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ksb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ksb_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ksf.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ksf_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ksh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ksh_de.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_arab.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_arab_iq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_arab_ir.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_iq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_ir.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_latn_sy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_latn_tr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_sy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ku_tr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/kw_gb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ky.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ky_kg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lag.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lag_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lg_ug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ln.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ln_cd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ln_cg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lo_la.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lt_lt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lu_cd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/luo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/luo_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/luy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/luy_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/lv_lv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mas.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mas_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mas_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mer.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mer_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mfe.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mfe_mu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mg_mg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mgh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mgh_mz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mi_nz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mk_mk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ml.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ml_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mn_cn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mn_cyrl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mn_cyrl_mn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mn_mn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mn_mong.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mn_mong_cn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mr_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ms.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ms_bn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ms_my.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mt_mt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mua.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/mua_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/my.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/my_mm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/naq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/naq_na.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nb.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nb_no.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nd_zw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nds.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nds_de.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ne.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ne_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ne_np.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nl_aw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nl_be.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nl_cw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nl_nl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nl_sx.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nmg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nmg_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nn_no.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/no.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nr_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nso.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nso_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nus.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nus_sd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ny.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ny_mw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nyn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/nyn_ug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/oc.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/oc_fr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/om.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/om_et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/om_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/or.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/or_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pa_arab.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pa_arab_pk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pa_guru.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pa_guru_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pa_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pa_pk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pl_pl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ps.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ps_af.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pt_ao.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pt_br.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pt_gw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pt_mz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pt_pt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/pt_st.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rm_ch.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rn_bi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ro.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ro_md.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ro_ro.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rof.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rof_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/root.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ru.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ru_md.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ru_ru.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ru_ua.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rw_rw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rwk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/rwk_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sa.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sa_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sah.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sah_ru.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/saq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/saq_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sbp.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sbp_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/se.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/se_fi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/se_no.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/seh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/seh_mz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ses.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ses_ml.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sg_cf.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sh_ba.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sh_cs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sh_yu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/shi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/shi_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/shi_latn_ma.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/shi_ma.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/shi_tfng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/shi_tfng_ma.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/si.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/si_lk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sid.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sid_et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sk_sk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sl_si.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sn_zw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/so.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/so_dj.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/so_et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/so_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/so_so.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sq_al.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_ba.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_cs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_cyrl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_cyrl_ba.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_cyrl_cs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_cyrl_me.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_cyrl_rs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_cyrl_yu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_latn_ba.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_latn_cs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_latn_me.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_latn_rs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_latn_yu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_me.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_rs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sr_yu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ss.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ss_sz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ss_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ssy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ssy_er.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/st.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/st_ls.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/st_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sv_fi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sv_se.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sw_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/sw_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/swc.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/swc_cd.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/syr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/syr_sy.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ta.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ta_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ta_lk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/te.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/te_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/teo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/teo_ke.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/teo_ug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tg_cyrl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tg_cyrl_tj.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tg_tj.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/th.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/th_th.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ti.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ti_er.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ti_et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tig.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tig_er.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tl_ph.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tn_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/to.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/to_to.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tr_tr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/trv.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/trv_tw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ts.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ts_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tt.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tt_ru.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/twq.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/twq_ne.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tzm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tzm_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tzm_latn_ma.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/tzm_ma.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ug_arab.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ug_arab_cn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ug_cn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uk_ua.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ur.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ur_in.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ur_pk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz_af.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz_arab.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz_arab_af.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz_cyrl.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz_cyrl_uz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz_latn_uz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/uz_uz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vai.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vai_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vai_latn_lr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vai_vaii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vai_vaii_lr.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ve.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/ve_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vi_vn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vun.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/vun_tz.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/wae.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/wae_ch.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/wal.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/wal_et.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/wo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/wo_latn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/wo_latn_sn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/wo_sn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/xh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/xh_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/xog.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/xog_ug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/yav.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/yav_cm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/yo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/yo_ng.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_cn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hans.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hans_cn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hans_hk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hans_mo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hans_sg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hant.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hant_hk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hant_mo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hant_tw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_hk.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_mo.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_sg.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zh_tw.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/data/zu_za.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/gettext/CGettextFile.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/gettext/CGettextMoFile.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/i18n/gettext/CGettextPoFile.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CChainedLogFilter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CDbLogRoute.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CEmailLogRoute.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CFileLogRoute.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CLogFilter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CLogRoute.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CLogRouter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CLogger.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CProfileLogRoute.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/logging/CWebLogRoute.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ar/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/bg/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/bg/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/bs/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ca/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ca/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/config.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/cs/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/cs/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/de/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/de/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/el/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/el/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/es/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/es/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/fa_ir/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/fa_ir/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/fi/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/fi/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/fr/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/fr/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/he/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/he/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/hu/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/hu/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/id/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/id/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/it/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/it/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ja/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ja/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/kk/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/kk/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ko_kr/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ko_kr/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/lt/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/lt/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/lv/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/lv/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/nl/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/nl/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/no/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/pl/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/pl/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/pt/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/pt/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/pt_br/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/pt_br/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ro/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ro/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ru/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ru/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/sk/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/sk/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/sr_sr/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/sr_sr/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/sr_yu/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/sr_yu/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/sv/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/sv/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ta_in/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/ta_in/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/th/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/tr/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/tr/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/uk/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/uk/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/vi/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/vi/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/zh_cn/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/zh_cn/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/zh_tw/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/messages/zh_tw/zii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/test/CDbFixtureManager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/test/CDbTestCase.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/test/CTestCase.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/test/CWebTestCase.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CDateTimeParser.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CFileHelper.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CFormatter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CLocalizedFormatter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CMarkdownParser.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CPasswordHelper.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CPropertyValue.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CTimestamp.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/CVarDumper.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/utils/mimeTypes.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CBooleanValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CCaptchaValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CCompareValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CDateValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CDefaultValueValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CEmailValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CExistValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CFileValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CFilterValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CInlineValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CNumberValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CRangeValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CRegularExpressionValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CRequiredValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CSafeValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CStringValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CTypeValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CUniqueValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CUnsafeValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CUrlValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/validators/CValidator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/Net_IDNA2/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/Net_IDNA2/Net/IDNA2.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/Net_IDNA2/Net/IDNA2/Exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/Net_IDNA2/Net/IDNA2/Exception/Nameprep.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/README.html create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/ABAP.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/CPP.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/CSS.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/DIFF.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/DTD.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Generator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/HTML.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/JAVA.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/JAVASCRIPT.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/MYSQL.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/PERL.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/PHP.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/PYTHON.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/RUBY.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Renderer.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Renderer/Array.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Renderer/BB.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Renderer/Console.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Renderer/Html.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Renderer/HtmlTags.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Renderer/JSON.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/Renderer/XML.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/SH.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/SQL.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/VBSCRIPT.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/Highlighter/XML.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/README create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/TODO create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/abap.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/cpp.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/css.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/diff.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/dtd.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/generate create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/generate.bat create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/html.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/java.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/javascript.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/mysql.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/package.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/perl.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/php.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/python.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/ruby.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/sample.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/sh.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/sql.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/vbscript.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/Text/xml.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/TextHighlighter/highlight.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/adodb/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/bbq/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/cldr/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/console-normalizer/README.md create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/console-normalizer/normalizeconsole.min.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/gettext/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/history/license.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/HTMLPurifier.standalone.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/Builder/Xml.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/Exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/Interchange.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/Interchange/Directive.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/Interchange/Id.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/InterchangeBuilder.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/Validator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/ValidatorAtom.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema.ser create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.Language.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.Base.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.Host.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/schema/info.ini create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/EntityLookup/entities.ser create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Filter/ExtractStyleBlocks.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Filter/YouTube.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Language/classes/en-x-test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Language/messages/en-x-test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Language/messages/en-x-testmini.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Language/messages/en.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Lexer/PH5P.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Printer.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Printer/CSSDefinition.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Printer/ConfigForm.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Printer/ConfigForm.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Printer/ConfigForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/htmlpurifier/standalone/HTMLPurifier/Printer/HTMLDefinition.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/jquery/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/jquery/autocomplete/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/jquery/maskedinput/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/jquery/treeview/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/jqueryui/MIT-LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/json/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/markdown/LICENSE.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/markdown/markdown.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/punycode/LICENSE-GPL.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/vendors/punycode/LICENSE-MIT.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ar/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/bg/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ca/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/de/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/el/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/es/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fi/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/fr/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/he/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/hr/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/id/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/it/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ja/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ko/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lt/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/lv/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/nl/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/no/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pl/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/pt_br/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ro/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/ru/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sk/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/sv/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/exception.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/uk/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/vi/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_cn/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/error.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/error400.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/error403.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/error404.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/error500.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/error503.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/log-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/log.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/profile-callstack-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/profile-callstack.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/profile-summary-firebug.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/views/zh_tw/profile-summary.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CActiveDataProvider.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CArrayDataProvider.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CAssetManager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CBaseController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CCacheHttpSession.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CClientScript.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CDataProvider.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CDataProviderIterator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CDbHttpSession.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CExtController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CFormModel.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CHttpCookie.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CHttpRequest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CHttpSession.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CHttpSessionIterator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/COutputEvent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CPagination.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CSort.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CSqlDataProvider.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CTheme.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CThemeManager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CUploadedFile.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CUrlManager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CWebApplication.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CWebModule.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/CWidgetFactory.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/actions/CAction.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/actions/CInlineAction.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/actions/CViewAction.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CAccessControlFilter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CAuthAssignment.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CAuthItem.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CAuthManager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CBaseUserIdentity.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CDbAuthManager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CPhpAuthManager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CUserIdentity.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/CWebUser.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/schema-mssql.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/schema-mysql.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/schema-oci.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/schema-pgsql.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/auth/schema-sqlite.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/filters/CFilter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/filters/CFilterChain.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/filters/CHttpCacheFilter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/filters/CInlineFilter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/form/CForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/form/CFormButtonElement.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/form/CFormElement.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/form/CFormElementCollection.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/form/CFormInputElement.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/form/CFormStringElement.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/helpers/CGoogleApi.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/helpers/CHtml.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/helpers/CJSON.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/helpers/CJavaScript.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/helpers/CJavaScriptExpression.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/packages.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/autocomplete/indicator.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/autocomplete/jquery.autocomplete.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.ajaxqueue.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.autocomplete.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.ba-bbq.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.ba-bbq.min.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.bgiframe.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.cookie.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.history.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.maskedinput.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.maskedinput.min.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.metadata.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.min.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.multifile.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.rating.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.treeview.async.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.treeview.edit.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.treeview.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.yii.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.yiiactiveform.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jquery.yiitab.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-icons_222222_256x240.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-icons_2e83ff_256x240.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-icons_454545_256x240.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-icons_888888_256x240.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/images/ui-icons_cd0a0a_256x240.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery-ui.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.accordion.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.autocomplete.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.button.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.core.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.datepicker.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.dialog.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.menu.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.progressbar.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.resizable.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.selectable.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.slider.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.spinner.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.tabs.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.theme.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/css/base/jquery.ui.tooltip.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/js/jquery-ui-i18n.min.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/jui/js/jquery-ui.min.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/punycode.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/punycode.min.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/rating/delete.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/rating/jquery.rating.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/rating/star.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/ajax-loader.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/file.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/folder-closed.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/folder.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/minus.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/plus.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-black-line.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-black.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-default-line.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-default.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-famfamfam-line.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-famfamfam.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-gray-line.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-gray.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-red-line.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/images/treeview-red.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/treeview/jquery.treeview.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/js/source/yiitab/jquery.yiitab.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/renderers/CPradoViewRenderer.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/renderers/CViewRenderer.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/services/CWebService.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/services/CWebServiceAction.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/services/CWsdlGenerator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CActiveForm.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CAutoComplete.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CClipWidget.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CContentDecorator.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CFilterWidget.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CFlexWidget.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CHtmlPurifier.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CInputWidget.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CMarkdown.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CMaskedTextField.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CMultiFileUpload.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/COutputCache.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/COutputProcessor.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CStarRating.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CTabView.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CTextHighlighter.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CTreeView.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/CWidget.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/captcha/CCaptcha.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/captcha/CCaptchaAction.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/captcha/SpicyRice.md create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/captcha/SpicyRice.ttf create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/pagers/CBasePager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/pagers/CLinkPager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/pagers/CListPager.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/pagers/pager.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/web/widgets/views/flexWidget.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/yii-powered.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/yiic create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/yiic.bat create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/yiic.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/yiilite.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/yiit.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/behaviors/CTimestampBehavior.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CBaseListView.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CBreadcrumbs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CDetailView.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CListView.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CMenu.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CPortlet.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/detailview/styles.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/bg.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/delete.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/down.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/jquery.yiigridview.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/loading.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/styles.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/up.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/update.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/view.png create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/down.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/jquery.yiilistview.js create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/loading.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/styles.css create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/up.gif create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CButtonColumn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CCheckBoxColumn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CDataColumn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CGridColumn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CGridView.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CLinkColumn.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiAccordion.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiAutoComplete.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiButton.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDatePicker.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDialog.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDraggable.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDroppable.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiInputWidget.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiProgressBar.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiResizable.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSelectable.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSlider.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSliderInput.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSortable.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiTabs.php create mode 100644 src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiWidget.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/css/main.css create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/ar/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/bg/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/ca/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/config.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/cs/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/de/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/de_de/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/el/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/es/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/fr/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/he/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/hu/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/id/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/it/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/ja/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/nl/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/no/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/pl/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/pt/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/pt_br/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/ro/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/ru/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/sk/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/sv/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/ta_in/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/uk/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/vi/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/zh_cn/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/messages/zh_tw/yii.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/.htaccess create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/ar/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/bg/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/ca/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/de/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/de_de/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/el/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/es/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/fr/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/he/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/it/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/ja/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/no/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/pl/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/pt/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/pt_br/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/ro/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/ru/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/sk/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/sv/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/uk/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/zh/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/zh_cn/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/requirements/views/zh_tw/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/TestApplication.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/TestHttpRequest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/assets/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/bootstrap.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/AnotherNewApplicationComponent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/BehaviorTestController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CApplicationComponentTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CBehaviorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CComponentTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CLogRouterTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CLoggerTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CModelTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CModuleTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CPropertyValueTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CSecurityManagerTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/CStatePersisterTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewApplicationComponent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewBeforeValidateBehavior.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewBehavior.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewComponent.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewFormModel.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewModel.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewModule.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/base/TestBehavior.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CCacheDependencyTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CDbCacheTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CDirectoryCacheDependencyTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CFileCacheDependencyTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CFileCacheTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CMemCacheTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CRedisCacheTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/cli/commands/MessageCommandTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CAttributeCollectionTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CConfigurationTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CListTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CMapTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CQueueTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CStackTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CTypedListTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CTypedMapTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/collections/data/config.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommand2Test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommandBuilderTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommandTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbConnectionTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbDataReaderTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbTransactionTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecord2Test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecordEventWrappersTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecordTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/models.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/models2.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/mssql.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/mysql.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/oci.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/postgres.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/sqlite.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CDbCriteriaTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMssqlTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMysql2Test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMysqlTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/COciTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CPostgres2Test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CPostgresTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CSqliteTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CDateFormatterTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CLocaleTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CNumberFormatterTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CPhpMessageSourceTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/YiiTTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/en/test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.mo create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.po create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/zh_cn/test.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/gettext/CGettextPoFileTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/messages/de_DE/testcategory.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CDateTimeParserTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CFileHelperTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CFormatterTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CLocalizedFormatterTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CBooleanValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CCompareValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CDateValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CDefaultValueValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CEmailValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CExistValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CFileValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CNumberValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CRangeValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CRequiredValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CStringValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CTypeValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CUniqueValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CUrlValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CValidatorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ModelMock.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ScenariosTestModel.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ValidatorTestModel.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CActiveDataProviderTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CArrayDataProviderTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CAssetManagerTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CClientScriptTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CControllerTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CCookieCollectionTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CDataProviderIteratorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpCookieTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpRequestTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpSessionTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSortTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSortTest.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSqlDataProviderTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUploadedFileTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUrlManagerTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUrlRuleTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/AuthManagerTestBase.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CDbAuthManagerTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CPhpAuthManagerTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CWebUserTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/SoapController.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/admin/index.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/article.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/home2.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/post.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CHtml/providerValue.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CHtmlTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJSONTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJavaScriptExpressionTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJavaScriptTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/CWsdlGeneratorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPerson.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPersonJuristic.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPersonPhysical.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationInput.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationOutput.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationResult.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CAutoCompleteTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CMaskedTextFieldTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CMultiFileUploadTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CStarRatingTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/zii/behaviors/CTimestampBehaviorTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/zii/behaviors/CTimestampBehaviorTest.sql create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/CGridViewTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/CListViewTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/grid/CButtonColumnTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/jui/CJuiButtonTest.php create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/phpunit.xml create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/readme.txt create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/reports/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/runtime/.gitignore create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/rununit.bat create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/travis/README.md create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/travis/memcache-setup.sh create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/travis/mysql-setup.sh create mode 100644 src/common/lib/vendor/yiisoft/yii/tests/travis/postgresql-setup.sh create mode 100644 src/common/messages/.gitkeep create mode 100644 src/common/models/.gitkeep create mode 100644 src/common/schema/.gitkeep create mode 100644 src/common/widgets/.gitkeep create mode 100644 src/composer.json create mode 100644 src/composer.lock create mode 100644 src/composer.phar create mode 100644 src/console/commands/.gitkeep create mode 100644 src/console/components/.gitkeep create mode 100644 src/console/config/console.php create mode 100644 src/console/config/env.php create mode 100644 src/console/config/env/dev.php create mode 100644 src/console/config/env/prod.php create mode 100644 src/console/data/.gitkeep create mode 100644 src/console/extensions/.gitkeep create mode 100644 src/console/migrations/.gitkeep create mode 100644 src/console/models/.gitkeep create mode 100644 src/frontend/components/.gitkeep create mode 100644 src/frontend/config/env.php create mode 100644 src/frontend/config/env/dev.php create mode 100644 src/frontend/config/env/prod.php create mode 100644 src/frontend/config/frontend.php create mode 100644 src/frontend/controllers/SiteController.php create mode 100644 src/frontend/extensions/.gitkeep create mode 100644 src/frontend/helpers/.gitkeep create mode 100644 src/frontend/lib/.gitkeep create mode 100644 src/frontend/models/.gitkeep create mode 100644 src/frontend/modules/.gitkeep create mode 100644 src/frontend/tests/.gitkeep create mode 100644 src/frontend/views/layouts/main.php create mode 100644 src/frontend/views/site/error.php create mode 100644 src/frontend/views/site/index.php create mode 100644 src/frontend/widgets/.gitkeep create mode 100644 src/frontend/www/.htaccess create mode 100644 src/frontend/www/apple-touch-icon-114x114-precomposed.png create mode 100644 src/frontend/www/apple-touch-icon-57x57-precomposed.png create mode 100644 src/frontend/www/apple-touch-icon-72x72-precomposed.png create mode 100644 src/frontend/www/apple-touch-icon-precomposed.png create mode 100644 src/frontend/www/apple-touch-icon.png create mode 100644 src/frontend/www/css/bootstrap-responsive.css create mode 100644 src/frontend/www/css/bootstrap-responsive.min.css create mode 100644 src/frontend/www/css/bootstrap.css create mode 100644 src/frontend/www/css/bootstrap.min.css create mode 100644 src/frontend/www/css/fonts/Chunkfive-webfont.eot create mode 100644 src/frontend/www/css/fonts/Chunkfive-webfont.svg create mode 100644 src/frontend/www/css/fonts/Chunkfive-webfont.ttf create mode 100644 src/frontend/www/css/fonts/Chunkfive-webfont.woff create mode 100644 src/frontend/www/css/fonts/League_Gothic-webfont.eot create mode 100644 src/frontend/www/css/fonts/League_Gothic-webfont.svg create mode 100644 src/frontend/www/css/fonts/League_Gothic-webfont.ttf create mode 100644 src/frontend/www/css/fonts/League_Gothic-webfont.woff create mode 100644 src/frontend/www/css/main.css create mode 100644 src/frontend/www/css/style.css create mode 100644 src/frontend/www/favicon.ico create mode 100644 src/frontend/www/humans.txt create mode 100644 src/frontend/www/img/github-logo.png create mode 100644 src/frontend/www/img/html5-logo-165-cut.png create mode 100644 src/frontend/www/index.php create mode 100644 src/frontend/www/js/libs/bootstrap.js create mode 100644 src/frontend/www/js/libs/bootstrap.min.js create mode 100644 src/frontend/www/js/libs/jquery-1.9.1.js create mode 100644 src/frontend/www/js/libs/jquery-1.9.1.min.js create mode 100644 src/frontend/www/js/libs/modernizr-2.0.6.min.js create mode 100644 src/frontend/www/js/libs/modernizr-2.6.2-respond-1.1.0.min.js create mode 100644 src/frontend/www/js/main.js create mode 100644 src/frontend/www/js/plugins.js create mode 100644 src/frontend/www/js/script.js create mode 100644 src/frontend/www/robots.txt create mode 100644 src/yiic create mode 100644 src/yiic.bat create mode 100644 src/yiic.php diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..f00b612 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,44 @@ +# cache directories +Thumbs.db +*.DS_Store +*.empty + +#phpstorm project files +.idea + +#netbeans project files +nbproject + +#eclipse, zend studio, aptana or other eclipse like project files +.buildpath +.project +.settings + +# sass cache files +*.sass-cache + +# mac deployment helpers +switch +index + +# runtime and cache directories +/console/runtime +/backend/www/assets +/backend/runtime +/frontend/www/assets +/frontend/runtime + +# configuration files +/console/config/env.php +/console/config/local.php +/backend/config/env.php +/backend/config/local.php +/frontend/config/env.php +/frontend/config/local.php + +# yiinitializr env.lock file +/common/lib/Yiinitializr/config/env.lock + +# composer +/common/lib/vendor +composer.lock diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..53d41cc --- /dev/null +++ b/src/README.md @@ -0,0 +1,134 @@ +YIInitializr-intermediate +======= +The following is a proposed project structure for basic to intermediate applications that works in conjunction with YIInitializr components. + +YIInitializr vanilla projects make extensive use of Composer. We found at [2amigos.us](http://2amigos.us) that is easier to your extensions bundle outside of your application scope - thanks to [Phundament](http://phundament.com) and Tobias Munk for his knowledge and shares. Composer is your dependency package best friend. + +The package is cleaned from extensions, you choose what you wish to include in your composer.json files. The only ones included are Yii Framework (obviously), [YiiStrap](https://github.com/yii-twbs/yiistrap) and [YiiWheels](https://github.com/2amigos/yiiwheels), the rest is up to you. We do not want to confuse you. + + +## Setup and first run + + * Set up Git by following the instructions [here](https://help.github.com/articles/set-up-git). + * Update the configurations in `api/config/`, `frontend/config/`, `console/config/`, `backend/config/` and `common/config/` to suit your needs. The `common/config/main.php` is configured to use **sqllite** by default. Change your `common/config/env/dev.php` to suit your database requirements. + * Composer is required The package includes already a `composer.phar` file. + * Browse through the `composer.json` and remove the dependencies you don't need also update the required versions of the extensions. + * If you have `composer` installed globally: + * Run `composer self-update` to make sure you have the latest version of composer. + * Run `composer install` to download all the dependencies. + * If you work the `composer.phar` library within the project boilerplate. + * Run `php composer.phar self-update` to make sure you have the latest version of composer. + * Run `php composer.phar install` to download all the dependencies. + * `Yiinitializr\Composer\Callback` will configure everything required on your application: `runtime` and `assets` folders and migrations. + + +For more information about using Composer please see its [documentation](http://getcomposer.org/doc/). + +###How to configure the application + +This boilerplate is very similar to YiiBoilerplate but differs from it for the easiness of its configuration. We focused to release the pain of configuring your application and combine your configuration files. `Yiinitializr\Helpers\Initializr` is very easy to use, check for example the bootstrap `index.php` file at the frontend: + +``` +require('./../../common/lib/vendor/autoload.php'); +require('./../../common/lib/vendor/yiisoft/yii/framework/yii.php'); + +Yii::setPathOfAlias('Yiinitializr', './../../common/lib/Yiinitializr'); + +use Yiinitializr\Helpers\Initializer; + +Initializer::create('./../', 'frontend', array( + __DIR__ .'/../../common/config/main.php', // files to merge with + __DIR__ .'/../../common/config/env.php', + __DIR__ .'/../../common/config/local.php', +))->run(); +``` + +For more information about Yiinitializr please check it at [its github repo](https://github.com/2amigos/yiinitializr). + +## Overall Structure + +Bellow the directory structure used: + +``` + |-backend + |---components + |---config + |-----env + |---controllers + |---extensions + |---helpers + |---lib + |---models + |---modules + |---tests + |---views + |-----layouts + |-----site + |---widgets + |---www + |-----css + |-------fonts + |-----img + |-----js + |-------libs + |-common + |---components + |---config + |-----env + |---extensions + |-----components + |---helpers + |---lib + |-----Yiinitializr + |-------Cli + |-------Composer + |-------Helpers + |-------config + |---messages + |---models + |---schema + |---widgets + |-console + |---commands + |---components + |---config + |-----env + |---data + |---extensions + |---migrations + |---models + |-frontend + |---components + |---config + |-----env + |---controllers + |---extensions + |---helpers + |---lib + |---models + |---modules + |---tests + |---views + |-----layouts + |-----site + |---widgets + |---www + |-----css + |-------fonts + |-----img + |-----js + |-------libs +``` + + +## Extensions + +The following extensions are part of YIInitializr-basic template: + + * Yiistrap [https://github.com/yii-twbs/yiistrap](https://github.com/yii-twbs/yiistrap) + * Yiiwheels [https://github.com/2amigos/yiiwheels](https://github.com/2amigos/yiiwheels) + * Yiinitializr [https://github.com/2amigos/yiinitializr](https://github.com/2amigos/yiinitializr) + +> [![2amigOS!](http://www.gravatar.com/avatar/55363394d72945ff7ed312556ec041e0.png)](http://www.2amigos.us) +web development has never been so fun +[www.2amigos.us](http://www.2amigos.us) diff --git a/src/backend/.htaccess b/src/backend/.htaccess new file mode 100644 index 0000000..8d2f256 --- /dev/null +++ b/src/backend/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/src/backend/components/.gitkeep b/src/backend/components/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/config/backend.php b/src/backend/config/backend.php new file mode 100644 index 0000000..a70894c --- /dev/null +++ b/src/backend/config/backend.php @@ -0,0 +1,66 @@ + + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +defined('APP_CONFIG_NAME') or define('APP_CONFIG_NAME', 'backend'); + +// web application configuration +return array( + 'name' => '{APPLICATION NAME}', + 'basePath' => realPath(__DIR__ . '/..'), + // path aliases + 'aliases' => array( + 'bootstrap' => dirname(__FILE__) . '/../..' . '/common/lib/vendor/2amigos/yiistrap', + 'yiiwheels' => dirname(__FILE__) . '/../..' . '/common/lib/vendor/2amigos/yiiwheels' + ), + + // application behaviors + 'behaviors' => array(), + + // controllers mappings + 'controllerMap' => array(), + + // application modules + 'modules' => array(), + + // application components + 'components' => array( + + 'bootstrap' => array( + 'class' => 'bootstrap.components.TbApi', + ), + + 'clientScript' => array( + 'scriptMap' => array( + 'bootstrap.min.css' => false, + 'bootstrap.min.js' => false, + 'bootstrap-yii.css' => false + ) + ), + 'urlManager' => array( + // uncomment the following if you have enabled Apache's Rewrite module. + 'urlFormat' => 'path', + 'showScriptName' => false, + + 'rules' => array( + // default rules + '/' => '/view', + '//' => '/', + '/' => '/', + ), + ), + 'user' => array( + 'allowAutoLogin' => true, + ), + 'errorHandler' => array( + 'errorAction' => 'site/error', + ) + ), +); \ No newline at end of file diff --git a/src/backend/config/env.php b/src/backend/config/env.php new file mode 100644 index 0000000..fec5127 --- /dev/null +++ b/src/backend/config/env.php @@ -0,0 +1,33 @@ + + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'modules' => array( + 'gii' => array( + 'class' => 'system.gii.GiiModule', + 'password' => 'yii', + 'ipFilters' => array('127.0.0.1','::1'), + ), + ), + 'components' => array( + 'db' => array( + 'connectionString' => 'mysql:host=localhost;dbname=factuges_dev', + 'username' => 'root', + 'password' => '', + 'enableProfiling' => true, + 'enableParamLogging' => true, + 'charset' => 'utf8', + ), + ), + 'params' => array( + 'yii.handleErrors' => true, + 'yii.debug' => true, + 'yii.traceLevel' => 3, + ) +); \ No newline at end of file diff --git a/src/backend/config/env/dev.php b/src/backend/config/env/dev.php new file mode 100644 index 0000000..fec5127 --- /dev/null +++ b/src/backend/config/env/dev.php @@ -0,0 +1,33 @@ + + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'modules' => array( + 'gii' => array( + 'class' => 'system.gii.GiiModule', + 'password' => 'yii', + 'ipFilters' => array('127.0.0.1','::1'), + ), + ), + 'components' => array( + 'db' => array( + 'connectionString' => 'mysql:host=localhost;dbname=factuges_dev', + 'username' => 'root', + 'password' => '', + 'enableProfiling' => true, + 'enableParamLogging' => true, + 'charset' => 'utf8', + ), + ), + 'params' => array( + 'yii.handleErrors' => true, + 'yii.debug' => true, + 'yii.traceLevel' => 3, + ) +); \ No newline at end of file diff --git a/src/backend/config/env/prod.php b/src/backend/config/env/prod.php new file mode 100644 index 0000000..d82309f --- /dev/null +++ b/src/backend/config/env/prod.php @@ -0,0 +1,27 @@ + + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'components' => array( +// 'db' => array( +// // setup to suit your needs +// 'connectionString' => '{DB_CONNECTION}', +// 'username' => '{DB_USER}', +// 'password' => '{DB_PASSWORD}', +// 'enableProfiling' => false, +// 'enableParamLogging' => false, +// 'charset' => 'utf8', +// ), + ), + 'params' => array( + 'yii.debug' => false, + 'yii.traceLevel' => 0, + 'yii.handleErrors' => APP_CONFIG_NAME !== 'test', + ) +); \ No newline at end of file diff --git a/src/backend/controllers/SiteController.php b/src/backend/controllers/SiteController.php new file mode 100644 index 0000000..a68dcec --- /dev/null +++ b/src/backend/controllers/SiteController.php @@ -0,0 +1,32 @@ + + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +class SiteController extends EController +{ + public function actionIndex() + { + $this->render('index'); + } + + /** + * This is the action to handle external exceptions. + */ + public function actionError() + { + if($error=Yii::app()->errorHandler->error) + { + if(Yii::app()->request->isAjaxRequest) + echo $error['message']; + else + $this->render('error', $error); + } + } +} \ No newline at end of file diff --git a/src/backend/extensions/.gitkeep b/src/backend/extensions/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/helpers/.gitkeep b/src/backend/helpers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/lib/.gitkeep b/src/backend/lib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/models/.gitkeep b/src/backend/models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/modules/.gitkeep b/src/backend/modules/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/tests/.gitkeep b/src/backend/tests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/views/layouts/main.php b/src/backend/views/layouts/main.php new file mode 100644 index 0000000..1810214 --- /dev/null +++ b/src/backend/views/layouts/main.php @@ -0,0 +1,106 @@ + + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/views/site/error.php b/src/backend/views/site/error.php new file mode 100644 index 0000000..b0b94db --- /dev/null +++ b/src/backend/views/site/error.php @@ -0,0 +1 @@ + diff --git a/src/backend/views/site/index.php b/src/backend/views/site/index.php new file mode 100644 index 0000000..842da30 --- /dev/null +++ b/src/backend/views/site/index.php @@ -0,0 +1,50 @@ +
+ + +
+

Hello, world!

+ +

This is a template for a simple marketing or informational website. It includes a large callout called the + hero unit and three supporting pieces of content. Use it as a starting point to create something more + unique.

+ +

Learn more »

+
+ + +
+
+

Heading

+ +

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris + condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis + euismod. Donec sed odio dui.

+ +

View details »

+
+
+

Heading

+ +

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris + condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis + euismod. Donec sed odio dui.

+ +

View details »

+
+
+

Heading

+ +

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula + porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut + fermentum massa justo sit amet risus.

+ +

View details »

+
+
+ +
+ +
+

© Company 2012

+
+
\ No newline at end of file diff --git a/src/backend/widgets/.gitkeep b/src/backend/widgets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/www/.htaccess b/src/backend/www/.htaccess new file mode 100644 index 0000000..27aed38 --- /dev/null +++ b/src/backend/www/.htaccess @@ -0,0 +1,550 @@ +# Apache configuration file +# httpd.apache.org/docs/2.2/mod/quickreference.html + +# Note .htaccess files are an overhead, this logic should be in your Apache +# config if possible: httpd.apache.org/docs/2.2/howto/htaccess.html + +# Techniques in here adapted from all over, including: +# Kroc Camen: camendesign.com/.htaccess +# perishablepress.com/press/2006/01/10/stupid-htaccess-tricks/ +# Sample .htaccess file of CMS MODx: modxcms.com + + +# ---------------------------------------------------------------------- +# Better website experience for IE users +# ---------------------------------------------------------------------- + +# Force the latest IE version, in various cases when it may fall back to IE7 mode +# github.com/rails/rails/commit/123eb25#commitcomment-118920 +# Use ChromeFrame if it's installed for a better experience for the poor IE folk + + + Header set X-UA-Compatible "IE=Edge,chrome=1" + # mod_headers can't match by content-type, but we don't want to send this header on *everything*... + + Header unset X-UA-Compatible + + + + +# ---------------------------------------------------------------------- +# Cross-domain AJAX requests +# ---------------------------------------------------------------------- + +# Serve cross-domain Ajax requests, disabled by default. +# enable-cors.org +# code.google.com/p/html5security/wiki/CrossOriginRequestSecurity + +# +# Header set Access-Control-Allow-Origin "*" +# + + +# ---------------------------------------------------------------------- +# CORS-enabled images (@crossorigin) +# ---------------------------------------------------------------------- + +# Send CORS headers if browsers request them; enabled by default for images. +# developer.mozilla.org/en/CORS_Enabled_Image +# blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html +# hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ +# wiki.mozilla.org/Security/Reviews/crossoriginAttribute + + + + # mod_headers, y u no match by Content-Type?! + + SetEnvIf Origin ":" IS_CORS + Header set Access-Control-Allow-Origin "*" env=IS_CORS + + + + + +# ---------------------------------------------------------------------- +# Webfont access +# ---------------------------------------------------------------------- + +# Allow access from all domains for webfonts. +# Alternatively you could only whitelist your +# subdomains like "subdomain.example.com". + + + + Header set Access-Control-Allow-Origin "*" + + + + +# ---------------------------------------------------------------------- +# Proper MIME type for all files +# ---------------------------------------------------------------------- + +# JavaScript +# Normalize to standard type (it's sniffed in IE anyways) +# tools.ietf.org/html/rfc4329#section-7.2 +AddType application/javascript js jsonp +AddType application/json json + +# Audio +AddType audio/ogg oga ogg +AddType audio/mp4 m4a f4a f4b + +# Video +AddType video/ogg ogv +AddType video/mp4 mp4 m4v f4v f4p +AddType video/webm webm +AddType video/x-flv flv + +# SVG +# Required for svg webfonts on iPad +# twitter.com/FontSquirrel/status/14855840545 +AddType image/svg+xml svg svgz +AddEncoding gzip svgz + +# Webfonts +AddType application/vnd.ms-fontobject eot +AddType application/x-font-ttf ttf ttc +AddType font/opentype otf +AddType application/x-font-woff woff + +# Assorted types +AddType image/x-icon ico +AddType image/webp webp +AddType text/cache-manifest appcache manifest +AddType text/x-component htc +AddType application/xml rss atom xml rdf +AddType application/x-chrome-extension crx +AddType application/x-opera-extension oex +AddType application/x-xpinstall xpi +AddType application/octet-stream safariextz +AddType application/x-web-app-manifest+json webapp +AddType text/x-vcard vcf +AddType application/x-shockwave-flash swf +AddType text/vtt vtt + + +# ---------------------------------------------------------------------- +# Allow concatenation from within specific js and css files +# ---------------------------------------------------------------------- + +# e.g. Inside of script.combined.js you could have +# +# +# and they would be included into this single file. + +# This is not in use in the boilerplate as it stands. You may +# choose to use this technique if you do not have a build process. + +# +# Options +Includes +# AddOutputFilterByType INCLUDES application/javascript application/json +# SetOutputFilter INCLUDES +# + +# +# Options +Includes +# AddOutputFilterByType INCLUDES text/css +# SetOutputFilter INCLUDES +# + + +# ---------------------------------------------------------------------- +# Gzip compression +# ---------------------------------------------------------------------- + + + + # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/ + + + SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding + RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding + + + + # Compress all output labeled with one of the following MIME-types + + AddOutputFilterByType DEFLATE application/atom+xml \ + application/javascript \ + application/json \ + application/rss+xml \ + application/vnd.ms-fontobject \ + application/x-font-ttf \ + application/xhtml+xml \ + application/xml \ + font/opentype \ + image/svg+xml \ + image/x-icon \ + text/css \ + text/html \ + text/plain \ + text/x-component \ + text/xml + + + + + +# ---------------------------------------------------------------------- +# Expires headers (for better cache control) +# ---------------------------------------------------------------------- + +# These are pretty far-future expires headers. +# They assume you control versioning with filename-based cache busting +# Additionally, consider that outdated proxies may miscache +# www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/ + +# If you don't use filenames to version, lower the CSS and JS to something like +# "access plus 1 week". + + + ExpiresActive on + +# Perhaps better to whitelist expires rules? Perhaps. + ExpiresDefault "access plus 1 month" + +# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5) + ExpiresByType text/cache-manifest "access plus 0 seconds" + +# Your document html + ExpiresByType text/html "access plus 0 seconds" + +# Data + ExpiresByType text/xml "access plus 0 seconds" + ExpiresByType application/xml "access plus 0 seconds" + ExpiresByType application/json "access plus 0 seconds" + +# Feed + ExpiresByType application/rss+xml "access plus 1 hour" + ExpiresByType application/atom+xml "access plus 1 hour" + +# Favicon (cannot be renamed) + ExpiresByType image/x-icon "access plus 1 week" + +# Media: images, video, audio + ExpiresByType image/gif "access plus 1 month" + ExpiresByType image/png "access plus 1 month" + ExpiresByType image/jpeg "access plus 1 month" + ExpiresByType video/ogg "access plus 1 month" + ExpiresByType audio/ogg "access plus 1 month" + ExpiresByType video/mp4 "access plus 1 month" + ExpiresByType video/webm "access plus 1 month" + +# HTC files (css3pie) + ExpiresByType text/x-component "access plus 1 month" + +# Webfonts + ExpiresByType application/x-font-ttf "access plus 1 month" + ExpiresByType font/opentype "access plus 1 month" + ExpiresByType application/x-font-woff "access plus 1 month" + ExpiresByType image/svg+xml "access plus 1 month" + ExpiresByType application/vnd.ms-fontobject "access plus 1 month" + +# CSS and JavaScript + ExpiresByType text/css "access plus 1 year" + ExpiresByType application/javascript "access plus 1 year" + + + + +# ---------------------------------------------------------------------- +# Prevent mobile network providers from modifying your site +# ---------------------------------------------------------------------- + +# The following header prevents modification of your code over 3G on some +# European providers. +# This is the official 'bypass' suggested by O2 in the UK. + +# +# Header set Cache-Control "no-transform" +# + + +# ---------------------------------------------------------------------- +# ETag removal +# ---------------------------------------------------------------------- + +# FileETag None is not enough for every server. + + Header unset ETag + + +# Since we're sending far-future expires, we don't need ETags for +# static content. +# developer.yahoo.com/performance/rules.html#etags +FileETag None + + +# ---------------------------------------------------------------------- +# Stop screen flicker in IE on CSS rollovers +# ---------------------------------------------------------------------- + +# The following directives stop screen flicker in IE on CSS rollovers - in +# combination with the "ExpiresByType" rules for images (see above). + +# BrowserMatch "MSIE" brokenvary=1 +# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 +# BrowserMatch "Opera" !brokenvary +# SetEnvIf brokenvary 1 force-no-vary + + +# ---------------------------------------------------------------------- +# Set Keep-Alive Header +# ---------------------------------------------------------------------- + +# Keep-Alive allows the server to send multiple requests through one +# TCP-connection. Be aware of possible disadvantages of this setting. Turn on +# if you serve a lot of static content. + +# +# Header set Connection Keep-Alive +# + + +# ---------------------------------------------------------------------- +# Cookie setting from iframes +# ---------------------------------------------------------------------- + +# Allow cookies to be set from iframes (for IE only) +# If needed, specify a path or regex in the Location directive. + +# +# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" +# + + +# ---------------------------------------------------------------------- +# Start rewrite engine +# ---------------------------------------------------------------------- + +# Turning on the rewrite engine is necessary for the following rules and +# features. FollowSymLinks must be enabled for this to work. + +# Some cloud hosting services require RewriteBase to be set: goo.gl/HOcPN +# If using the h5bp in a subdirectory, use `RewriteBase /foo` instead where +# 'foo' is your directory. + +# If your web host doesn't allow the FollowSymlinks option, you may need to +# comment it out and use `Options +SymLinksIfOwnerMatch`, but be aware of the +# performance impact: http://goo.gl/Mluzd + + + Options +FollowSymlinks +# Options +SymLinksIfOwnerMatch + RewriteEngine On +# RewriteBase / +# If you are in a sub folder of your web root you +# might have to enable something like this: +# +# RewriteBase /~antonio/app/frontend/www + +# Yii rewrite + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + + RewriteRule . index.php + + + +# ---------------------------------------------------------------------- +# Suppress or force the "www." at the beginning of URLs +# ---------------------------------------------------------------------- + +# The same content should never be available under two different URLs - +# especially not with and without "www." at the beginning, since this can cause +# SEO problems (duplicate content). That's why you should choose one of the +# alternatives and redirect the other one. + +# By default option 1 (no "www.") is activated. +# no-www.org/faq.php?q=class_b + +# If you'd prefer to use option 2, just comment out all option 1 lines +# and uncomment option 2. + +# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! + +# ---------------------------------------------------------------------- + +# Option 1: +# Rewrite "www.example.com -> example.com". + + + RewriteCond %{HTTPS} !=on + RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] + RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] + + +# ---------------------------------------------------------------------- + +# Option 2: +# Rewrite "example.com -> www.example.com". +# Be aware that the following rule might not be a good idea if you use "real" +# subdomains for certain parts of your website. + +# +# RewriteCond %{HTTPS} !=on +# RewriteCond %{HTTP_HOST} !^www\..+$ [NC] +# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] +# + + +# ---------------------------------------------------------------------- +# Built-in filename-based cache busting +# ---------------------------------------------------------------------- + +# If you're not using the build script to manage your filename version revving, +# you might want to consider enabling this, which will route requests for +# `/css/style.20110203.css` to `/css/style.css`. + +# To understand why this is important and a better idea than all.css?v1231, +# please refer to the bundled documentation about `.htaccess`. + +# +# RewriteCond %{REQUEST_FILENAME} !-f +# RewriteCond %{REQUEST_FILENAME} !-d +# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] +# + + +# ---------------------------------------------------------------------- +# Prevent SSL cert warnings +# ---------------------------------------------------------------------- + +# Rewrite secure requests properly to prevent SSL cert warnings, e.g. prevent +# https://www.example.com when your cert only allows https://secure.example.com + +# +# RewriteCond %{SERVER_PORT} !^443 +# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] +# + + +# ---------------------------------------------------------------------- +# Prevent 404 errors for non-existing redirected folders +# ---------------------------------------------------------------------- + +# without -MultiViews, Apache will give a 404 for a rewrite if a folder of the +# same name does not exist. +# webmasterworld.com/apache/3808792.htm + +Options -MultiViews + + +# ---------------------------------------------------------------------- +# Custom 404 page +# ---------------------------------------------------------------------- + +# You can add custom pages to handle 500 or 403 pretty easily, if you like. +# If you are hosting your site in subdirectory, adjust this accordingly +# e.g. ErrorDocument 404 /subdir/404.html +# ErrorDocument 404 /404.html + + +# ---------------------------------------------------------------------- +# UTF-8 encoding +# ---------------------------------------------------------------------- + +# Use UTF-8 encoding for anything served text/plain or text/html +AddDefaultCharset utf-8 + +# Force UTF-8 for a number of file formats +AddCharset utf-8 .atom .css .js .json .rss .vtt .xml + + +# ---------------------------------------------------------------------- +# A little more security +# ---------------------------------------------------------------------- + +# To avoid displaying the exact version number of Apache being used, add the +# following to httpd.conf (it will not work in .htaccess): +# ServerTokens Prod + +# "-Indexes" will have Apache block users from browsing folders without a +# default document Usually you should leave this activated, because you +# shouldn't allow everybody to surf through every folder on your server (which +# includes rather private places like CMS system folders). + + Options -Indexes + + +# Block access to "hidden" directories or files whose names begin with a +# period. This includes directories used by version control systems such as +# Subversion or Git. + + RewriteCond %{SCRIPT_FILENAME} -d [OR] + RewriteCond %{SCRIPT_FILENAME} -f + RewriteRule "(^|/)\." - [F] + + +# Block access to backup and source files. These files may be left by some +# text/html editors and pose a great security danger, when anyone can access +# them. + + Order allow,deny + Deny from all + Satisfy All + + +# If your server is not already configured as such, the following directive +# should be uncommented in order to set PHP's register_globals option to OFF. +# This closes a major security hole that is abused by most XSS (cross-site +# scripting) attacks. For more information: http://php.net/register_globals +# +# IF REGISTER_GLOBALS DIRECTIVE CAUSES 500 INTERNAL SERVER ERRORS: +# +# Your server does not allow PHP directives to be set via .htaccess. In that +# case you must make this change in your php.ini file instead. If you are +# using a commercial web host, contact the administrators for assistance in +# doing this. Not all servers allow local php.ini files, and they should +# include all PHP configurations (not just this one), or you will effectively +# reset everything to PHP defaults. Consult www.php.net for more detailed +# information about setting PHP directives. + +# php_flag register_globals Off + +# Rename session cookie to something else, than PHPSESSID +# php_value session.name sid + +# Disable magic quotes (This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.) +# php_flag magic_quotes_gpc Off + +# Do not show you are using PHP +# Note: Move this line to php.ini since it won't work in .htaccess +# php_flag expose_php Off + +# Level of log detail - log all errors +# php_value error_reporting -1 + +# Write errors to log file +# php_flag log_errors On + +# Do not display errors in browser (production - Off, development - On) +# php_flag display_errors Off + +# Do not display startup errors (production - Off, development - On) +# php_flag display_startup_errors Off + +# Format errors in plain text +# Note: Leave this setting 'On' for xdebug's var_dump() output +# php_flag html_errors Off + +# Show multiple occurrence of error +# php_flag ignore_repeated_errors Off + +# Show same errors from different sources +# php_flag ignore_repeated_source Off + +# Size limit for error messages +# php_value log_errors_max_len 1024 + +# Don't precede error with string (doesn't accept empty string, use whitespace if you need) +# php_value error_prepend_string " " + +# Don't prepend to error (doesn't accept empty string, use whitespace if you need) +# php_value error_append_string " " + +# Increase cookie security + + php_value session.cookie_httponly true + \ No newline at end of file diff --git a/src/backend/www/apple-touch-icon-114x114-precomposed.png b/src/backend/www/apple-touch-icon-114x114-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..de2d59f92cae78ec291461ca1d5de47763d391b7 GIT binary patch literal 1032 zcmeAS@N?(olHy`uVBq!ia0vp^MIg+<3?z3jm-+*#0|7oEuAb@nZs`RN(~N;6gyEN- z3+F;afLxc<-216Uktu06Q;aSr89OFso=Gq|7H4E1o0=0FZWo=jH`;JpgkgDvpKW;D zx=@4W5U0gK2G&90GXjhz`Wf5!1$w)=1UXs7S!-)r+QeFEhMQ~Xn3@KeshgM>`I@NP z8)~ZP>Z<7JDQT!GsbfcqsNymzDsrkSdow=8F)%PQd%8G=WZZi@)BpS;1A%sR+c&*$ z4rRxAiiikxNM-MQ%e(*o_NY_xYdcEPPHnom#8!Cz2MgoBy-r(yG4_A)fT0urIah|c zuUhkOuhAxsY;`r}nO(uPeWyexdUdQ>$9N;aYLmbs!)gXI5s5h0nCO>w@nnXFXq9+=A&U?x1Ul;f~EnA@YTF=q#8R6z( zD`#x%%elB?)o#;r3+to%Jp*)Cy?&Oq=h2(mwjF!c=^(^1Z;VTkQ^F*Baf8yB(H2UdM6w4Aaf*n7iNo zPICtAP5U*^E9RQrf=XGZ$LD$L-!f0So}Te%WBp!VjlJg3{JyXvXji1P(VQC(;_NIr zt2e7&(@FTZXvWhq3W!gXN{7{s|D6G&dN?~ zQ^@(Boy%*oFoPT!igj|>RqhB{O7*jqws{Tulo4VTdKX25diY4w6@I{R}PqLv#F{+q{jceJoAA1B_ig4IEwcZR~U{taMDxH4Kf^_4Jjr zG!->9)HGCev{aQfR29`#l~9o~Di>My>B*mV3=E9bo-U3d9>?EKJJ{D`Akg;w+T=Bj zS9(=C8bnx9Y~JPG`@eRZYtok6WfR^^v=p4AU-RelbcXL+nWcA5v?(!`<3v{M z)9bAbYp(6(EKE3I=pCPCK6!$d=Gop$XDW*AihUGqs#TWW*%m6`v(o;>lBu6<4L>%E zzTEIdhCSUW`PoC2ONC6?`P+`3W1V)zwXJ*ifv|voy~~!K{&L{5z`gWL_hvOIMWv%= z4`rt=QM>GXzWjylGTWnJCUHeua-#oE3f#S9d#mfSz30*bAHSXJx9c#|C(YUWU#((& zqBC2e_I&D@^?tDhr_-(+ee}9;?u0mQf4@z?yI!p{?KfIZFjlG{O zyMNt1d)LlDH}j;EcQ@aEUMZaW=-O8QnMY>deQ#L&DoQ2j@eA`;{s~9&mYO{|TDU#& pw)vHfi|;$f=GO;F|2+Rh|Lbff^@O$?_P`{?;OXk;vd$@?2>^oK4mtn; literal 0 HcmV?d00001 diff --git a/src/backend/www/apple-touch-icon-72x72-precomposed.png b/src/backend/www/apple-touch-icon-72x72-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..b20e78ef3920a3f46e552fe179c5d59dabd675c6 GIT binary patch literal 747 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAk#fdHQn*N17wXy|^Lv0Hip4CT9| z=7yza-Apk~PENU;WaONb?HHeaBF@l0Hf3*=fo){M)^Pom;U{jZOSb)V+<>-3-<3_0=2=)U0&Xl(e;tv{g-Y)bzDg zl{A1zO977@wzny-%ui1ddb?@mU zITMj6r-e%t6a_iYR)zihzkilUMrQZt1si6t{%lw*b9|q~kI0t?*lsyUzo>6eS;xGJ zS*Od?fywLWqa;fWrp7rNOEgz7a(p-|o(}GK~_(^P;m#IBg6Po2TkYR=e#L*=_qH=J_q2Uo|P) z!i!(9s;=7c{EhbS&({~W3U8h9w(8u;o9?+um%Z569$K!b8vA*}v99lPB7T;Z`ECtq zn(#2{j(bdUqTKgGyg+`v0xHV0x`<;{g^T^Bkol>QuU8^e%ok|-*F25^mV)}G- zi}ZZ%}Z`jN>C*MDPKi=H@v=D=sacAx84d*Ys zWpmqHE%54nyU^he#gChq)i$T_9Lio4=XAV@c}t{$*c>lb=W@@3bL(-Y=(-m@Db7Ssln68nS`TlMqoB5}otKT`zx%0i)Pv4^LrGC&| wo3_Lgm3HZCH?BQgY*hVQ^sa++M(hRo#B*|C9>pOFz|_m&>FVdQ&MBb@0NJQ0PXGV_ literal 0 HcmV?d00001 diff --git a/src/backend/www/apple-touch-icon-precomposed.png b/src/backend/www/apple-touch-icon-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..6d2fc3969d2a377bc1b0e345e20ef5c15bd21a2f GIT binary patch literal 640 zcmeAS@N?(olHy`uVBq!ia0vp^mLSZ*3?z3SE8Y&I4g~mwxIRoXMnezMjNH--+|u*G zWWl{uBiGct8!5&vDY;%L*%y6@I{R}PqLv#F{+q{jceJoAA1B_ig4IEwcZR~U{taMDxH4Kf^_4Jjr zG!->9)HGCev{aQfR29`#l~9o~Di>My>B*mV3=E9bo-U3d9>?EKJJ{D`Akg;w+T=Bj zS9(=C8bnx9Y~JPG`@eRZYtok6WfR^^v=p4AU-RelbcXL+nWcA5v?(!`<3v{M z)9bAbYp(6(EKE3I=pCPCK6!$d=Gop$XDW*AihUGqs#TWW*%m6`v(o;>lBu6<4L>%E zzTEIdhCSUW`PoC2ONC6?`P+`3W1V)zwXJ*ifv|voy~~!K{&L{5z`gWL_hvOIMWv%= z4`rt=QM>GXzWjylGTWnJCUHeua-#oE3f#S9d#mfSz30*bAHSXJx9c#|C(YUWU#((& zqBC2e_I&D@^?tDhr_-(+ee}9;?u0mQf4@z?yI!p{?KfIZFjlG{O zyMNt1d)LlDH}j;EcQ@aEUMZaW=-O8QnMY>deQ#L&DoQ2j@eA`;{s~9&mYO{|TDU#& pw)vHfi|;$f=GO;F|2+Rh|Lbff^@O$?_P`{?;OXk;vd$@?2>^oK4mtn; literal 0 HcmV?d00001 diff --git a/src/backend/www/apple-touch-icon.png b/src/backend/www/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6d2fc3969d2a377bc1b0e345e20ef5c15bd21a2f GIT binary patch literal 640 zcmeAS@N?(olHy`uVBq!ia0vp^mLSZ*3?z3SE8Y&I4g~mwxIRoXMnezMjNH--+|u*G zWWl{uBiGct8!5&vDY;%L*%y6@I{R}PqLv#F{+q{jceJoAA1B_ig4IEwcZR~U{taMDxH4Kf^_4Jjr zG!->9)HGCev{aQfR29`#l~9o~Di>My>B*mV3=E9bo-U3d9>?EKJJ{D`Akg;w+T=Bj zS9(=C8bnx9Y~JPG`@eRZYtok6WfR^^v=p4AU-RelbcXL+nWcA5v?(!`<3v{M z)9bAbYp(6(EKE3I=pCPCK6!$d=Gop$XDW*AihUGqs#TWW*%m6`v(o;>lBu6<4L>%E zzTEIdhCSUW`PoC2ONC6?`P+`3W1V)zwXJ*ifv|voy~~!K{&L{5z`gWL_hvOIMWv%= z4`rt=QM>GXzWjylGTWnJCUHeua-#oE3f#S9d#mfSz30*bAHSXJx9c#|C(YUWU#((& zqBC2e_I&D@^?tDhr_-(+ee}9;?u0mQf4@z?yI!p{?KfIZFjlG{O zyMNt1d)LlDH}j;EcQ@aEUMZaW=-O8QnMY>deQ#L&DoQ2j@eA`;{s~9&mYO{|TDU#& pw)vHfi|;$f=GO;F|2+Rh|Lbff^@O$?_P`{?;OXk;vd$@?2>^oK4mtn; literal 0 HcmV?d00001 diff --git a/src/backend/www/css/bootstrap-responsive.css b/src/backend/www/css/bootstrap-responsive.css new file mode 100644 index 0000000..5215a5d --- /dev/null +++ b/src/backend/www/css/bootstrap-responsive.css @@ -0,0 +1,1109 @@ +/*! + * Bootstrap Responsive v2.3.0 + * + * 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/src/backend/www/css/bootstrap-responsive.min.css b/src/backend/www/css/bootstrap-responsive.min.css new file mode 100644 index 0000000..0597860 --- /dev/null +++ b/src/backend/www/css/bootstrap-responsive.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap Responsive v2.3.0 + * + * 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:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-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:#999}.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:#111}.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:0;-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:#111;border-bottom-color:#111}.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/src/backend/www/css/bootstrap.css b/src/backend/www/css/bootstrap.css new file mode 100644 index 0000000..b255056 --- /dev/null +++ b/src/backend/www/css/bootstrap.css @@ -0,0 +1,6158 @@ +/*! + * Bootstrap v2.3.0 + * + * 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/src/backend/www/css/bootstrap.min.css b/src/backend/www/css/bootstrap.min.css new file mode 100644 index 0000000..fd5ed73 --- /dev/null +++ b/src/backend/www/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.3.0 + * + * 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:.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:#333;background-color:#fff}a{color:#08c;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:#999}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:#999}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 #eee}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 #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;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:#333;-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:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}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:#555;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:#fff;border:1px solid #ccc;-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 .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .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;-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;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}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:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-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:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.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:#eee}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 #fff;background-color:#eee;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;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.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 #ddd}.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 #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;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 #ddd}.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}.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 #000;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:#fff;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 #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#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:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#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:#999}.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 #000;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:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.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 .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.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:#333;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,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*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:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .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:.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:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #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:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;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:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;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:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;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:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;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:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;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:#fff;background-color:#222;*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:#08c;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:#333;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:#04c}.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:#222}.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:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*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:#eee}.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:#999;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:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.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 #fff}.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:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;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:#fff;background-color:#08c}.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:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.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:#555;border-bottom-color:#555}.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:#fff;background-color:#999;border-color:#999}.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:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.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:#eee #ddd #eee #eee}.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:#fff}.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:#eee #eee #eee #ddd}.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:#fff}.nav>.disabled>a{color:#999}.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,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#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:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;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:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;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:#fff;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:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \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 #fff;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 #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.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:#555;border-bottom-color:#555}.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,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);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:#999;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:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.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:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.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:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-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:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;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:#fff;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 #000;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:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \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 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.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:#fff;border:1px solid #ddd;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:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;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:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;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:0;-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 .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .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 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.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:.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:#fff;text-align:center;text-decoration:none;background-color:#000;-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:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;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:#fff;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:#fff;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:#fff;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:#fff;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:#fff;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 .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-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:#555}.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:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.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:#fff;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:#333}.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:#fff;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 .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .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:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.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:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.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:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.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:#eee;-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/src/backend/www/css/fonts/Chunkfive-webfont.eot b/src/backend/www/css/fonts/Chunkfive-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..a540c2590b54e1c2b40cd0bdc8d9efe412cb8a59 GIT binary patch literal 18610 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 + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Generated in 2009 by FontLab Studio Copyright info pending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/www/css/fonts/Chunkfive-webfont.ttf b/src/backend/www/css/fonts/Chunkfive-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2dc041a3ee4286a1b508a4fd5a3c5d4e193c6769 GIT binary patch literal 18412 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 literal 0 HcmV?d00001 diff --git a/src/backend/www/css/fonts/Chunkfive-webfont.woff b/src/backend/www/css/fonts/Chunkfive-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..b2048008ae66fa9b1afb30fcd69c2a1bddef44a9 GIT binary patch literal 12136 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 a^tzgW8b}iH8gP0sU=7s&I$AXt^#2FO|Le5? literal 0 HcmV?d00001 diff --git a/src/backend/www/css/fonts/League_Gothic-webfont.eot b/src/backend/www/css/fonts/League_Gothic-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..e354b5616665ebb6c333b9564ad0e3c937365187 GIT binary patch literal 25486 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 literal 0 HcmV?d00001 diff --git a/src/backend/www/css/fonts/League_Gothic-webfont.svg b/src/backend/www/css/fonts/League_Gothic-webfont.svg new file mode 100644 index 0000000..d41ff8b --- /dev/null +++ b/src/backend/www/css/fonts/League_Gothic-webfont.svg @@ -0,0 +1,148 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Generated in 2009 by FontLab Studio Copyright info pending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/www/css/fonts/League_Gothic-webfont.ttf b/src/backend/www/css/fonts/League_Gothic-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7ea9d0dd395024eefff514984bd93aa5bfabf8fb GIT binary patch literal 25272 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 literal 0 HcmV?d00001 diff --git a/src/backend/www/css/main.css b/src/backend/www/css/main.css new file mode 100644 index 0000000..b25e769 --- /dev/null +++ b/src/backend/www/css/main.css @@ -0,0 +1,22 @@ + + +/* ========================================================================== + Author's custom styles + ========================================================================== */ + + + + + + + + + + + + + + + + + diff --git a/src/backend/www/css/style.css b/src/backend/www/css/style.css new file mode 100644 index 0000000..a3d2cb2 --- /dev/null +++ b/src/backend/www/css/style.css @@ -0,0 +1,767 @@ +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } +audio[controls], canvas, video { display: inline-block; *display: inline; *zoom: 1; } +html { font-size: 100%; overflow-y: scroll; -webkit-overflow-scrolling: touch; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } +body { margin: 0; font-size: 13px; line-height: 1.231; } +body, button, input, select, textarea { font-family: sans-serif; color: #222; } +::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; } +::selection { background: #fe57a1; color: #fff; text-shadow: none; } +a { color: #00e; } +a:visited { color: #551a8b; } +a:focus { outline: thin dotted; } +a:hover, a:active { outline: 0; } +abbr[title] { border-bottom: 1px dotted; } +b, strong { font-weight: bold; } +blockquote { margin: 1em 40px; } +dfn { font-style: italic; } +hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } +ins { background: #ff9; color: #000; text-decoration: none; } +mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } +pre, code, kbd, samp { font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 1em; } +pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } +q { quotes: none; } +q:before, q:after { content: ""; content: none; } +small { font-size: 85%; } +sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } +sup { top: -0.5em; } +sub { bottom: -0.25em; } +ul, ol { margin: 1em 0; padding: 0 0 0 40px; } +dd { margin: 0 0 0 40px; } +nav ul, nav ol { list-style: none; margin: 0; padding: 0; } +img { border: 0; -ms-interpolation-mode: bicubic; } +svg:not(:root) { + overflow: hidden; +} +figure { margin: 0; } +form { margin: 0; } +fieldset { border: 0; margin: 0; padding: 0; } +legend { border: 0; *margin-left: -7px; padding: 0; } +label { cursor: pointer; } +button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } +button, input { line-height: normal; *overflow: visible; } +button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; } +input[type="checkbox"], input[type="radio"] { box-sizing: border-box; } +input[type="search"] { -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; } +button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } +textarea { overflow: auto; vertical-align: top; } +input:valid, textarea:valid { } +input:invalid, textarea:invalid { background-color: #f0dddd; } +table { border-collapse: collapse; border-spacing: 0; } + + + + + + +@font-face { + font-family: 'ChunkFiveRegular'; + src: url('fonts/Chunkfive-webfont.eot'); + src: url('fonts/Chunkfive-webfont.eot?#iefix') format('embedded-opentype'), + url('fonts/Chunkfive-webfont.woff') format('woff'), + url('fonts/Chunkfive-webfont.ttf') format('truetype'), + url('fonts/Chunkfive-webfont.svg#ChunkFiveRegular') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'LeagueGothicRegular'; + src: url('fonts/League_Gothic-webfont.eot'); + src: url('fonts/League_Gothic-webfont.eot?#iefix') format('embedded-opentype'), + url('fonts/League_Gothic-webfont.woff') format('woff'), + url('fonts/League_Gothic-webfont.ttf') format('truetype'), + url('fonts/League_Gothic-webfont.svg#LeagueGothicRegular') format('svg'); + font-weight: normal; + font-style: normal; +} + + + +/* =================================================== + Initializr styles + http://verekia.com/initializr/responsive-template + Author: Jonathan Verrecchia + =================================================== */ + +body{ font:16px/26px Helvetica, Helvetica Neue, Arial; } + +.wrapper{ + width:90%; + margin:0 5%; +} + +/* =================== + ALL: Orange Theme + =================== */ + +#header-container{ border-bottom: 13px solid #e44d26; } +#footer-container{ border-top: 20px solid #e44d26; } +#main aside { border-top: 20px solid #e44d26; } + +#header-container, +#footer-container, +#main aside{ + background:#f16529; +} + +#title{ + color:white; + font-family:'ChunkFiveRegular'; + font-weight:normal; + font-size:4em; + margin-bottom:20px; +} + +#header-container h2{ + color:white; + font-size:16px; +} + +#header-container header{ + text-align:center; +} + +::-moz-selection { background: #f16529; color: #fff; text-shadow: none; } +::selection { background: #f16529; color: #fff; text-shadow: none; } + + + +/* WEBSITE */ + +#html5-logo-container{ + display:none; +} + +#follow-container{ + display:none; +} + + + #badges{ + margin:0 auto; + width:265px; + margin-top:10px; + line-height:18px; + font-size:14px; + color:white; + font-weight:bold; + font-style:italic; + + } + + #badges li{ + float:left; + background:#eee; + color:#444; + text-align:center; + width:85px; + height:85px; +/* border:10px solid #E44D26; */ + -webkit-border-radius:999px; + -moz-border-radius:999px; + border-radius:999px; + margin-left:5px; + text-shadow:0 2px 1px white; + box-shadow:1px 1px 1px rgba(0, 0, 0, 0.4); + } + + #badges li:first-child{ + margin-left:0; + } + + .badge-label{ + margin-top:26px; + } + + #badges ul{ + float:right; + margin:0; + list-style-type:none; + padding:0; + } + + +.separator{ + font-family:LeagueGothicRegular; + text-align:center; + font-weight:normal; + font-size:3em; + color:#F16529; + margin:50px 0; +} + +.separator:before, +.separator:after{ + width:20%; + height:4px; + display:block; + background:#eee; + content:""; + margin-top:14px; + display:none; +} + + +.separator:before{ + float:left; +} + +.separator:after{ + float:right; +} + +#fine-tuning-separator{ + margin:30px 0 20px; +} + +.blank-background button, +.blank-background a{ + background:#bbb; +} + +.blank-background button:hover, +.blank-background a:hover{ + background:#c4c4c4; +} + +.blank-background button:active{ + background:#888; +} + + + +.initializr-background button, +.initializr-background a, +#download-section a{ + background:#F16529; +} + +.initializr-background button:hover, +.initializr-background a:hover, +#download-section a:hover{ + background:#F67539; +} + +.initializr-background button:active{ + background:#d14509; +} + +.bootstrap-background button, +.bootstrap-background a{ + background:#6090ff; +} + +.bootstrap-background button:hover, +.bootstrap-background a:hover{ + background:#78a0ff; +} + +.bootstrap-background button:active{ + background:#4070df; +} + +#preconfig-section{ + padding-bottom:10px; +} + +.preconfig-container{ + display:block; + width:100%; +} + +.preconfig-block{ + border:none; + display:block; + width:100%; +} + +#preconfig-section h3, +#download-section a +{ + font-weight:normal; + font-family:ChunkFiveRegular; + font-size:2em; + color:white; + margin:0; + text-align:center; + padding:25px 0; + text-shadow:0 -2px 2px rgba(0, 0, 0, 0.1); + color:white; +} + +.preconfig-links-container{ + width:100px; + margin:6px auto; +} + +#preconfig-section a{ + padding:4px; + color:white; + font-weight:bold; + text-decoration:none; + margin:0px; + -webkit-border-radius:0 3px 3px 0; + -moz-border-radius:0 3px 3px 0; + border-radius:0 3px 3px 0; +} + +#preconfig-section a.first{ + -webkit-border-radius:3px 0 0 3px; + -moz-border-radius:3px 0 0 3px; + border-radius:3px 0 0 3px; +} + + +#main{ + padding:30px 0; +} + +#customize-section label{ + background:white; + -webkit-border-radius:4px; + -moz-border-radius:4px; + border-radius:4px; + + border:1px solid #ccc; + border-top:0; + border-left:0; + + padding:4px 8px; + display:block; + margin:0 5px 5px 0; +} + +#customize-section label:hover{ + background:#f5f5f5; +} + +#customize-section input{ + margin-right:6px; +} + +.customize-section h3{ + text-align:center; + font-weight:normal; + font-family:LeagueGothicRegular; + font-size:2em; +} + +.second-h5bp-label, +.third-h5bp-label{ + display:none; + visibility:hidden; +} + +.customize-section a{ + color:#E44D26; + text-decoration:none; +} + +textarea{ + display:block; + width:700px; +} + +#download-section{ + margin-top:50px; +} + +#download-section a{ + background:#F16529; + display:block; + text-decoration:none; + margin-bottom:20px; +} + + +#about-container{ + background:#eee; + padding:30px 0; +} + +#about-container h3{ + font-weight:normal; + font-family:LeagueGothicRegular; + font-size:2em; +} + +#about-container a{ + color:#E44D26; +/* font-weight:bold; */ + text-decoration:none; +} + +#github-container img{ + display:none; +} + + +#email:before{ + content:"initializr@gmail.com"; +} + +/* =============== + ALL: IE Fixes + =============== */ + +.ie7 #title{ padding-top:20px; } + + + +/* ============================================================================= + Non-semantic helper classes + Please define your styles before this section. + ========================================================================== */ + +/* For image replacement */ +.ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; text-align: left; direction: ltr; } +.ir br { display: none; } + +/* Hide for both screenreaders and browsers: + css-discuss.incutio.com/wiki/Screenreader_Visibility */ +.hidden { display: none; visibility: hidden; } + +/* Hide only visually, but have it available for screenreaders: by Jon Neal. + www.webaim.org/techniques/css/invisiblecontent/ & j.mp/visuallyhidden */ +.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } + +/* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: drupal.org/node/897638 */ +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } + +/* Hide visually and from screenreaders, but maintain layout */ +.invisible { visibility: hidden; } + +/* Contain floats: nicolasgallagher.com/micro-clearfix-hack/ */ +.clearfix:before, .clearfix:after { content: ""; display: table; } +.clearfix:after { clear: both; } +.clearfix { zoom: 1; } + + +/* ==|== media queries ====================================================== */ + +@media only screen and (min-width: 540px) { + +/* ==================== + INTERMEDIATE: Menu + ==================== */ + + #header-container{ + -webkit-box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); + -moz-box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); + box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); + } + + #header-container header{ + text-align:left; + height:133px; + } + + + .ie7 #header-container header, + .ie8 #header-container header{ + height:auto; + } + + #title, + #header-container h2, + #follow-container p{ + text-shadow:0 -2px 2px rgba(0, 0, 0, 0.1); + } + + #title-container{ + float:left; + width:63%; + } + + #html5-logo-container{ + float:left; + width:0; + } + + #follow-iframes-container{ + width:260px; + float:right; + } + + #follow-iframes-container iframe{ + float:right; + width:146px!important; + margin-bottom:6px; + } + + .ie9 #follow-iframes-container iframe, + .ie8 #follow-iframes-container iframe, + .ie7 #follow-iframes-container iframe{ + width:135px!important; + } + + + #follow-container{ + float:right; + width:37%; + display:block; + } + + #follow-container p{ + text-align:right; + color:white; + font-weight:bold; + margin:12px 0; + } + + + + #follow-container a{ + color:white; + } + + #intro p{ +/* float:left; */ + margin-right:285px; + } + + #badges{ + float:right; + } + + .separator:before, + .separator:after{ + width:20%; + display:block; + } + + .preconfig-container{ + float:left; + width:48%; + margin:0 1%; + } + + .preconfig-block{ + } + + .preconfig-container:last-child{ + margin:auto; + float:none; + clear:both; + } + + #hidden-section{ + display:none; + } + + .customize-section{ + float:left; + width:50%; + } + + .customize-section:nth-child(2n + 1){ + clear:both; + } + + .second-h5bp-label{ + display:block; + } + + #download-section a{ + float:left; + width:48%; + } + + #download-section a:first-child{ + margin-right:4%; + } + + #about-container{ + -webkit-box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); + + } + + #about-container article{ + width:100%; + } + + #github-container{ + margin:auto; + width:480px; + } + + #github-container img{ + float:left; + display:block; + } + + #github-repositories{ + float:right; + margin-top:20px; + } + + #github-repositories h3{ + text-align:center; + } + +} + +@media only screen and (min-width: 860px) { + + #title-container{ + float:left; + width:40%; + } + + #html5-logo-container{ + display:block; + float:left; + width:20%; + } + + #html5-logo-container img{ + display:block; + margin:auto; + } + + #follow-iframes-container{ + width:260px; + float:right; + } + + #follow-container{ + float:right; + width:40%; + } + + #follow-container p:before{ + content:"Initialized by "; + } + + #follow-iframes-container iframe{ +/* float:right; */ + width:auto!important; + margin-bottom:6px; + } + + .ie9 #follow-iframes-container iframe, + .ie8 #follow-iframes-container iframe, + .ie7 #follow-iframes-container iframe{ + width:auto!important; + } + + #intro p{ +/* width:56%; */ + } + + #intro #badges{ +/* width:44%; */ + } + + .separator:before, + .separator:after{ + width:31%; + } + + .preconfig-container{ + width:32%; + margin-right:2%; + margin-left:0; + } + + .preconfig-block{ + } + + .ie8 .preconfig-container, + .ie7 .preconfig-container{ + width:31.33%; + } + + .preconfig-container:last-child{ + margin:0; + float:left; + clear:none; + } + + + .first-h5bp-label{ + visibility:hidden; + } + + .second-h5bp-label{ + visibility:visible; + } + + .third-h5bp-label{ + display:block; + } + + + + .customize-section{ + width:33.3%; + } + + .customize-section:nth-child(2n + 1){ + clear:none; + } + + .customize-section:nth-child(3n + 1){ + clear:both; + } + + + #about-container article{ + width:530px; + } + + #github-container{ + float:right; + } + + #github-container img{ + float:none; + margin:0; + } + + #github-repositories{ + float:none; + margin:0; + } + + #github-container{ + width:auto; + } + + +} + + +@media only screen and (min-width: 1140px) { + +/* =============== + Maximal Width + =============== */ + + .wrapper{ + width:1026px; /* 1140px - 10% for margins */ + margin:0 auto; + } +} + + +/* ============================================================================= + Print styles. + Inlined to avoid required HTTP connection: www.phpied.com/delay-loading-your-print-css/ + ========================================================================== */ + +@media print { + * { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: sanbeiji.com/archives/953 */ + a, a:visited { color: #444 !important; 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: ""; } /* Don't show links for images, or javascript/internal links */ + pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } + thead { display: table-header-group; } /* css-discuss.incutio.com/wiki/Printing_Tables */ + 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; } +} diff --git a/src/backend/www/favicon.ico b/src/backend/www/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4ec0d298859a6e33a6cc40f7a502354b8cad5f76 GIT binary patch literal 1150 zcmZvc&rcIU6vv0?T~3}Vg?4v#yIp9zU1&k*FC;0yN&pE-r71xP79vXcVT>0+io~c1 z@uXK{B+(d6OeFpaN@9YEe?#HwsR-_La3ytienMto~)nRwQ- ztEU+|%NSFI377ELelaj6V$~l2tkU-O_ua*{^@FsA{g}@8q9dxKtviRl!Uob8+Ta!EAg$QvH?ga$D;u=7jC-I3O|)O%LUjBohDWow zICCGdrSIq+zm4V)7dd%ttzd{992)p}!V915J%{L}2T0!ff%9UY*uq!DZ@fotY!u;; zX657PiH$^CemQGdZh)@35gRKaxwM1C!WSeLx6xjBh3x1cW+(a)Yd0au_8EwEcrMo? z6gJQ~@d&A#Hk+9Lgv9)3Bo@CRI{6%#ksRiyhLGurTeTsU&cH?9ej|$5l_!YLeL(Em z8!>K)-xsXdBQ^KV${{lK5~)lcopIBu6|wgHNl^7h_yW!FH3p#g6d1kJ)*Ym0pP{F_ z6SAg53mD*f@Z|i&p43m&UQtACgmJkJTBrpbb03kpyo^>;fh5%*$L-vy=EPDDIQ`?? zBaNIlpe_Fx10z}ZRJ-Ptai@QXr(T?%DZH+X6CdcvAYh0yD}QTF8q!wwuhYl$ZW!U< z0rjZWr<9K>?&f$+vH!h44o_ogZ{NMVvQ|u{(z`B~x9oCBWtx+ZVwGB&AG#SUpJ8nK U6k~U4Y^(l{aMn(ow8Rkm2iEifo&W#< literal 0 HcmV?d00001 diff --git a/src/backend/www/humans.txt b/src/backend/www/humans.txt new file mode 100644 index 0000000..59cb7a4 --- /dev/null +++ b/src/backend/www/humans.txt @@ -0,0 +1,20 @@ +# humanstxt.org/ +# The humans responsible & technology colophon + +/* TEAM */ + + Senior Developer: Antonio Ramirez + Contact: amigo.cobos [at] gmail.com + Twitter: @tonydspaniard + From: Majorca, Catalonia, Spain + +/* THANKS */ + + (First) Phundamente man: Tobias Munk + From: Stuttgart, Schwabenland, Germany + +/* SITE */ + Standards: HTML5, CSS3 + Components: JQuery, Modernizr, Yii Framework + Doctype: HTML5 + IDE: PhpStorm 6.0 diff --git a/src/backend/www/img/github-logo.png b/src/backend/www/img/github-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..29a95df0b223c9ed4d024495d423c7cc4f69e34c GIT binary patch literal 22194 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 MOsz~BFzyNe1Kmqyp#T5? literal 0 HcmV?d00001 diff --git a/src/backend/www/img/html5-logo-165-cut.png b/src/backend/www/img/html5-logo-165-cut.png new file mode 100644 index 0000000000000000000000000000000000000000..205fa69a885e51ce30dc27e9fb7cb375adc316ba GIT binary patch literal 6472 zcmV-O8Mo$%P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000hiNklEvVulmNrdDQB1GL9USM z7-g!U>~&7*WE+&#ZrsVqDk%54W^=L)$`RLWPPReW?V8QWHYi73vpLxYPPReW z@0!giPSuky*JtF(q*PJpDF2=aIU%C$=fL+J3Det23e_$tf^r-v0^%-i=LM)vn6&WE>b4c^jKW|{2jL>}4=l`42hK?vO6X-?ioqZpU z_o=2HD}3%T^A6SCfxmKXvg4|6-Dey~5mX4CydN<#poThLGOxWJC`%Yj_Lcp;gm1iH zykT;;eLqnsTfh1Zv3wTZc9?$#e0cge6g zLGa}LpBX-RiGW!Tlp%(bGGu=*!PckE!*TtlM4)Wh@J-|Qoc!}cpKbNTdWm{Rv3;f= zG~D`(dAGdmYP|Liv-jL^H-$xK8@*>`^cZ6M6DLkKRY*>z1xoV;WD{e_xaIBNGkU*y zx87^~HI|-#d$CdVLfJ!twL0M&FBo5&&TqUczCXUWgTm)7F#3ARJ^PUR->s$VPEGecNy0m2 z7+-!|urRhY_`>GU)y1jXOpGs~wg4J2VaOFy3+2aHB-3u$NTP=6^t75?QV3*FiMEQ=Fq9>mpiE?JS!dj`Q!LpObWY zH_dGh+j_>9hF5v=8}F()t<7|LTD4?0ZE6I{G8XQ@X1pYK z4ry(LO+Pp9k||UpP>usfY1i`I7HC2!tv&bK^aci}OKUToo_6BK0?h^G5u0C}=_0dJO?XTu zUYxcVtck{y!rE77xFmOaTAK(}`j_eSv>Hlgn_^69^H=#?>d)sP@cvu4Q^nNTYoe1%G(jk%&5~} zKpBwKP8oA`OT$HGXW#Q1+S}WW+^fco1)2s*fP-myu}SQoZe%PO*~S81W}q~`S7n`r z@=28BrphHnkQpeu%tL9nTbeAqigf#xgzLT2?UcEE{ZMAeEh8UGdfDl|%^ynNVC*mM z4Gc`|Fj3RS0!=*8G3%6`-*7h*cafQi?z`q~~joKw+DF*ZW z%s^R8;~SeqNv?BAb5KrVc?w&W+%h(o%ovnKEZD2ES==(~E*Yg$_NTQ0(&U!S;F3{6 zSw@`}kxGd@yCN?#iz_5F`RX&7cgZNB>`!weq+w0mNXe|19Vo$)4OHuPwuH_UpVL^< zNXe|1DJTci-euVAmTBHtAW10u)7}s^yJea;7Dy7xV_9en8{M+mTrx^1kCKM6h#K57 zc+Rd6(Zn+k&}@nd$}v(>7BQ<^CU8pbsg$K+u%w)FA`>l=(3#>VQ&vi5lY(*t+v~qm z=9bOsl2OmT$1>9@7Pw`zx@444g4zQ;GfL7eo7p9!hVsKqwammAK|&#-(&k^%%!(4q zv8**txbAEGPPRc=BBkZFPT7UBNXj$Now5n#QP-qSwsqfwu1TGo zQ#v^)Pa{c2$|9Vy10`5^D7}+|a>6yKlWkBQaZT!E84)-D)EVGTPR=Qv9F(Whm>W~pFVB+0m9hpUz_^3U!PSWJG5pOg2cwg1P!2j6 zoowsA4?7^8Y;(%P4n`;2pd4^8I@#8JcR3)PY=d&d0qJBLl&L*H)G51A24rjpHfNIA zaLPW{v`#ibS;6fqK+e{6N8Ythf0w0Y^T#TXgV6vPCzK&++ks6=2u@zIUVh+5g!^|RJr6l= z0U}pG_&Ee1ggD`nQWA!>&-28QgH(2Iq5SXDJX|BG?jqiLB!xu*!Kb9-=2W8&LOvawSx45Rd^Sy zgfq{9N=5ztbVm!yggyHRKY5?<<6Q)Mb|Cw^Aql`!H|5f@*RcxxbTee-yPGZ$HH%ds+k&E;@cf!t(bJ*& zw}gxn$_nZPG6!WEK-3vNA^;Ie!jdE?QwYm)ujkjC8=KSb`{Tg9HbPlKmD;X$@4DS? zC@PYm1Yt!gCUTVk`E{64LuYix?UX}~0Lwts5Q-4OvLq;i5E3NEL99Aw17Ls5~06^RVhzf~cG$Z|c3G+1ICcVyR{)tCf`LX8c>iX<#USQdzI zD(lUg_Pa3++XiihvfGhj#tD&nTv*mHRwPo)bU;H{ZO1(TxgLw~eLph+wmcGNOK{o_sAPFiEl%*OQ1`5I%FuM_X-fC@PYmtYU@L@!>Qh zRKIU;zf%PMOM?e|#SLW_a2+auegkkda1pSi=|QZnpoAJgwSt1wf$M3(YnwF=8~}Cz zF9L6&YW@S8p+tuVUe%WmEC;Rvt^~dYtZ25Gay3j7R;E@_raK{a!`KJB32X!Y1H4Vd zHU6eEPzA78Uw;J729^QW0yhGyw2S6a&!MM3f`OhX2i1^`K!&Q;tjeI}Za4rO0$u_B z4*XC5EVk2%lTM312E3!M2Z5!)I$*v2`emRcg~mu&hM*(~%Tp^TCqQej_USHpr*_1> z7~C7mwp{%#eLW2<0?yZfejT_BXio*C9+XCvBT8>($i_m2+8jFdxNsZrF%2eFWC_aY z8U^0h*YAPF8qlkNujnzUwV@^{RrhTvi-B&}oxmIVI$+DgrKzfE5O`i+^HF)4R{%F@ zSUb|#)f=5Nt1&(0sLE!*Ix%- zOR`ID1}HzPq8rBJ@`DZ61X1NfQpT_Sv^0V*&`eT z{t0YF1+PEFmJMnhlyynyF71$hQ$a0zUV~Z!T?<@n*)w-*Cwxag^LxY?xOPz5p%3-- zsGb~MtS3shpb|;WOkfhXM+3NBe}ABv-Vg`nlq70hw@<_Hpq?OIi&~?e zwF7R`Gv!X2v8q$-g1nk!1!tKDzH1VOT4$Am6iV8Vx(OvpV4dxA~jHfo;9lxY! i$-7Z&%uciD{{sNS-!75 + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +require('./../../common/lib/vendor/autoload.php'); + +Yiinitializr\Helpers\Initializer::create('./../', 'backend', array( + __DIR__ .'/../../common/config/main.php', + __DIR__ .'/../../common/config/env.php', + __DIR__ .'/../../common/config/local.php', + 'main', + 'env', + 'local' +))->run(); \ No newline at end of file diff --git a/src/backend/www/js/libs/bootstrap.js b/src/backend/www/js/libs/bootstrap.js new file mode 100644 index 0000000..a81171b --- /dev/null +++ b/src/backend/www/js/libs/bootstrap.js @@ -0,0 +1,2268 @@ +/* =================================================== + * bootstrap-transition.js v2.3.0 + * 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.0 + * 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.0 + * 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.0 + * 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() + } + 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.0 + * 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.0 + * 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('.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.0 + * 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.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 = $('

" + (o[0] > 0 && I == o[1] - 1 ? '
' : "") : ""), F += U + } + B += F + } + return B += x + ($.ui.ie6 && !e.inline ? '' : ""), e._keyEvent = !1, B + }, _generateMonthYearHeader: function (e, t, n, r, i, s, o, u) { + var a = this._get(e, "changeMonth"), f = this._get(e, "changeYear"), l = this._get(e, "showMonthAfterYear"), c = '
', h = ""; + if (s || !a)h += '' + o[t] + ""; else { + var p = r && r.getFullYear() == n, d = i && i.getFullYear() == n; + h += '" + } + l || (c += h + (s || !a || !f ? " " : "")); + if (!e.yearshtml) { + e.yearshtml = ""; + if (s || !f)c += '' + n + ""; else { + var m = this._get(e, "yearRange").split(":"), g = (new Date).getFullYear(), y = function (e) { + var t = e.match(/c[+-].*/) ? n + parseInt(e.substring(1), 10) : e.match(/[+-].*/) ? g + parseInt(e, 10) : parseInt(e, 10); + return isNaN(t) ? g : t + }, b = y(m[0]), w = Math.max(b, y(m[1] || "")); + b = r ? Math.max(b, r.getFullYear()) : b, w = i ? Math.min(w, i.getFullYear()) : w, e.yearshtml += '", c += e.yearshtml, e.yearshtml = null + } + } + return c += this._get(e, "yearSuffix"), l && (c += (s || !a || !f ? " " : "") + h), c += "
", c + }, _adjustInstDate: function (e, t, n) { + var r = e.drawYear + (n == "Y" ? t : 0), i = e.drawMonth + (n == "M" ? t : 0), s = Math.min(e.selectedDay, this._getDaysInMonth(r, i)) + (n == "D" ? t : 0), o = this._restrictMinMax(e, this._daylightSavingAdjust(new Date(r, i, s))); + e.selectedDay = o.getDate(), e.drawMonth = e.selectedMonth = o.getMonth(), e.drawYear = e.selectedYear = o.getFullYear(), (n == "M" || n == "Y") && this._notifyChange(e) + }, _restrictMinMax: function (e, t) { + var n = this._getMinMaxDate(e, "min"), r = this._getMinMaxDate(e, "max"), i = n && t < n ? n : t; + return i = r && i > r ? r : i, i + }, _notifyChange: function (e) { + var t = this._get(e, "onChangeMonthYear"); + t && t.apply(e.input ? e.input[0] : null, [e.selectedYear, e.selectedMonth + 1, e]) + }, _getNumberOfMonths: function (e) { + var t = this._get(e, "numberOfMonths"); + return t == null ? [1, 1] : typeof t == "number" ? [1, t] : t + }, _getMinMaxDate: function (e, t) { + return this._determineDate(e, this._get(e, t + "Date"), null) + }, _getDaysInMonth: function (e, t) { + return 32 - this._daylightSavingAdjust(new Date(e, t, 32)).getDate() + }, _getFirstDayOfMonth: function (e, t) { + return(new Date(e, t, 1)).getDay() + }, _canAdjustMonth: function (e, t, n, r) { + var i = this._getNumberOfMonths(e), s = this._daylightSavingAdjust(new Date(n, r + (t < 0 ? t : i[0] * i[1]), 1)); + return t < 0 && s.setDate(this._getDaysInMonth(s.getFullYear(), s.getMonth())), this._isInRange(e, s) + }, _isInRange: function (e, t) { + var n = this._getMinMaxDate(e, "min"), r = this._getMinMaxDate(e, "max"); + return(!n || t.getTime() >= n.getTime()) && (!r || t.getTime() <= r.getTime()) + }, _getFormatConfig: function (e) { + var t = this._get(e, "shortYearCutoff"); + return t = typeof t != "string" ? t : (new Date).getFullYear() % 100 + parseInt(t, 10), {shortYearCutoff: t, dayNamesShort: this._get(e, "dayNamesShort"), dayNames: this._get(e, "dayNames"), monthNamesShort: this._get(e, "monthNamesShort"), monthNames: this._get(e, "monthNames")} + }, _formatDate: function (e, t, n, r) { + t || (e.currentDay = e.selectedDay, e.currentMonth = e.selectedMonth, e.currentYear = e.selectedYear); + var i = t ? typeof t == "object" ? t : this._daylightSavingAdjust(new Date(r, n, t)) : this._daylightSavingAdjust(new Date(e.currentYear, e.currentMonth, e.currentDay)); + return this.formatDate(this._get(e, "dateFormat"), i, this._getFormatConfig(e)) + }}), $.fn.datepicker = function (e) { + if (!this.length)return this; + $.datepicker.initialized || ($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv), $.datepicker.initialized = !0); + var t = Array.prototype.slice.call(arguments, 1); + return typeof e != "string" || e != "isDisabled" && e != "getDate" && e != "widget" ? e == "option" && arguments.length == 2 && typeof arguments[1] == "string" ? $.datepicker["_" + e + "Datepicker"].apply($.datepicker, [this[0]].concat(t)) : this.each(function () { + typeof e == "string" ? $.datepicker["_" + e + "Datepicker"].apply($.datepicker, [this].concat(t)) : $.datepicker._attachDatepicker(this, e) + }) : $.datepicker["_" + e + "Datepicker"].apply($.datepicker, [this[0]].concat(t)) + }, $.datepicker = new Datepicker, $.datepicker.initialized = !1, $.datepicker.uuid = (new Date).getTime(), $.datepicker.version = "1.9.1", window["DP_jQuery_" + dpuuid] = $ +})(jQuery); +(function (e, t) { + var n = "ui-dialog ui-widget ui-widget-content ui-corner-all ", r = {buttons: !0, height: !0, maxHeight: !0, maxWidth: !0, minHeight: !0, minWidth: !0, width: !0}, i = {maxHeight: !0, maxWidth: !0, minHeight: !0, minWidth: !0}; + e.widget("ui.dialog", {version: "1.9.1", options: {autoOpen: !0, buttons: {}, closeOnEscape: !0, closeText: "close", dialogClass: "", draggable: !0, hide: null, height: "auto", maxHeight: !1, maxWidth: !1, minHeight: 150, minWidth: 150, modal: !1, position: {my: "center", at: "center", of: window, collision: "fit", using: function (t) { + var n = e(this).css(t).offset().top; + n < 0 && e(this).css("top", t.top - n) + }}, resizable: !0, show: null, stack: !0, title: "", width: 300, zIndex: 1e3}, _create: function () { + this.originalTitle = this.element.attr("title"), typeof this.originalTitle != "string" && (this.originalTitle = ""), this.oldPosition = {parent: this.element.parent(), index: this.element.parent().children().index(this.element)}, this.options.title = this.options.title || this.originalTitle; + var t = this, r = this.options, i = r.title || " ", s, o, u, a, f; + s = (this.uiDialog = e("
")).addClass(n + r.dialogClass).css({display: "none", outline: 0, zIndex: r.zIndex}).attr("tabIndex", -1).keydown(function (n) { + r.closeOnEscape && !n.isDefaultPrevented() && n.keyCode && n.keyCode === e.ui.keyCode.ESCAPE && (t.close(n), n.preventDefault()) + }).mousedown(function (e) { + t.moveToTop(!1, e) + }).appendTo("body"), this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s), o = (this.uiDialogTitlebar = e("
")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").bind("mousedown",function () { + s.focus() + }).prependTo(s), u = e("").addClass("ui-dialog-titlebar-close ui-corner-all").attr("role", "button").click(function (e) { + e.preventDefault(), t.close(e) + }).appendTo(o), (this.uiDialogTitlebarCloseText = e("")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(u), a = e("").uniqueId().addClass("ui-dialog-title").html(i).prependTo(o), f = (this.uiDialogButtonPane = e("
")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"), (this.uiButtonSet = e("
")).addClass("ui-dialog-buttonset").appendTo(f), s.attr({role: "dialog", "aria-labelledby": a.attr("id")}), o.find("*").add(o).disableSelection(), this._hoverable(u), this._focusable(u), r.draggable && e.fn.draggable && this._makeDraggable(), r.resizable && e.fn.resizable && this._makeResizable(), this._createButtons(r.buttons), this._isOpen = !1, e.fn.bgiframe && s.bgiframe(), this._on(s, {keydown: function (t) { + if (!r.modal || t.keyCode !== e.ui.keyCode.TAB)return; + var n = e(":tabbable", s), i = n.filter(":first"), o = n.filter(":last"); + if (t.target === o[0] && !t.shiftKey)return i.focus(1), !1; + if (t.target === i[0] && t.shiftKey)return o.focus(1), !1 + }}) + }, _init: function () { + this.options.autoOpen && this.open() + }, _destroy: function () { + var e, t = this.oldPosition; + this.overlay && this.overlay.destroy(), this.uiDialog.hide(), this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"), this.uiDialog.remove(), this.originalTitle && this.element.attr("title", this.originalTitle), e = t.parent.children().eq(t.index), e.length && e[0] !== this.element[0] ? e.before(this.element) : t.parent.append(this.element) + }, widget: function () { + return this.uiDialog + }, close: function (t) { + var n = this, r, i; + if (!this._isOpen)return; + if (!1 === this._trigger("beforeClose", t))return; + return this._isOpen = !1, this.overlay && this.overlay.destroy(), this.options.hide ? this._hide(this.uiDialog, this.options.hide, function () { + n._trigger("close", t) + }) : (this.uiDialog.hide(), this._trigger("close", t)), e.ui.dialog.overlay.resize(), this.options.modal && (r = 0, e(".ui-dialog").each(function () { + this !== n.uiDialog[0] && (i = e(this).css("z-index"), isNaN(i) || (r = Math.max(r, i))) + }), e.ui.dialog.maxZ = r), this + }, isOpen: function () { + return this._isOpen + }, moveToTop: function (t, n) { + var r = this.options, i; + return r.modal && !t || !r.stack && !r.modal ? this._trigger("focus", n) : (r.zIndex > e.ui.dialog.maxZ && (e.ui.dialog.maxZ = r.zIndex), this.overlay && (e.ui.dialog.maxZ += 1, e.ui.dialog.overlay.maxZ = e.ui.dialog.maxZ, this.overlay.$el.css("z-index", e.ui.dialog.overlay.maxZ)), i = {scrollTop: this.element.scrollTop(), scrollLeft: this.element.scrollLeft()}, e.ui.dialog.maxZ += 1, this.uiDialog.css("z-index", e.ui.dialog.maxZ), this.element.attr(i), this._trigger("focus", n), this) + }, open: function () { + if (this._isOpen)return; + var t, n = this.options, r = this.uiDialog; + return this._size(), this._position(n.position), r.show(n.show), this.overlay = n.modal ? new e.ui.dialog.overlay(this) : null, this.moveToTop(!0), t = this.element.find(":tabbable"), t.length || (t = this.uiDialogButtonPane.find(":tabbable"), t.length || (t = r)), t.eq(0).focus(), this._isOpen = !0, this._trigger("open"), this + }, _createButtons: function (t) { + var n = this, r = !1; + this.uiDialogButtonPane.remove(), this.uiButtonSet.empty(), typeof t == "object" && t !== null && e.each(t, function () { + return!(r = !0) + }), r ? (e.each(t, function (t, r) { + r = e.isFunction(r) ? {click: r, text: t} : r; + var i = e("").attr(r, !0).unbind("click").click(function () { + r.click.apply(n.element[0], arguments) + }).appendTo(n.uiButtonSet); + e.fn.button && i.button() + }), this.uiDialog.addClass("ui-dialog-buttons"), this.uiDialogButtonPane.appendTo(this.uiDialog)) : this.uiDialog.removeClass("ui-dialog-buttons") + }, _makeDraggable: function () { + function r(e) { + return{position: e.position, offset: e.offset} + } + + var t = this, n = this.options; + this.uiDialog.draggable({cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", handle: ".ui-dialog-titlebar", containment: "document", start: function (n, i) { + e(this).addClass("ui-dialog-dragging"), t._trigger("dragStart", n, r(i)) + }, drag: function (e, n) { + t._trigger("drag", e, r(n)) + }, stop: function (i, s) { + n.position = [s.position.left - t.document.scrollLeft(), s.position.top - t.document.scrollTop()], e(this).removeClass("ui-dialog-dragging"), t._trigger("dragStop", i, r(s)), e.ui.dialog.overlay.resize() + }}) + }, _makeResizable: function (n) { + function u(e) { + return{originalPosition: e.originalPosition, originalSize: e.originalSize, position: e.position, size: e.size} + } + + n = n === t ? this.options.resizable : n; + var r = this, i = this.options, s = this.uiDialog.css("position"), o = typeof n == "string" ? n : "n,e,s,w,se,sw,ne,nw"; + this.uiDialog.resizable({cancel: ".ui-dialog-content", containment: "document", alsoResize: this.element, maxWidth: i.maxWidth, maxHeight: i.maxHeight, minWidth: i.minWidth, minHeight: this._minHeight(), handles: o, start: function (t, n) { + e(this).addClass("ui-dialog-resizing"), r._trigger("resizeStart", t, u(n)) + }, resize: function (e, t) { + r._trigger("resize", e, u(t)) + }, stop: function (t, n) { + e(this).removeClass("ui-dialog-resizing"), i.height = e(this).height(), i.width = e(this).width(), r._trigger("resizeStop", t, u(n)), e.ui.dialog.overlay.resize() + }}).css("position", s).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se") + }, _minHeight: function () { + var e = this.options; + return e.height === "auto" ? e.minHeight : Math.min(e.minHeight, e.height) + }, _position: function (t) { + var n = [], r = [0, 0], i; + if (t) { + if (typeof t == "string" || typeof t == "object" && "0"in t)n = t.split ? t.split(" ") : [t[0], t[1]], n.length === 1 && (n[1] = n[0]), e.each(["left", "top"], function (e, t) { + +n[e] === n[e] && (r[e] = n[e], n[e] = t) + }), t = {my: n[0] + (r[0] < 0 ? r[0] : "+" + r[0]) + " " + n[1] + (r[1] < 0 ? r[1] : "+" + r[1]), at: n.join(" ")}; + t = e.extend({}, e.ui.dialog.prototype.options.position, t) + } else t = e.ui.dialog.prototype.options.position; + i = this.uiDialog.is(":visible"), i || this.uiDialog.show(), this.uiDialog.position(t), i || this.uiDialog.hide() + }, _setOptions: function (t) { + var n = this, s = {}, o = !1; + e.each(t, function (e, t) { + n._setOption(e, t), e in r && (o = !0), e in i && (s[e] = t) + }), o && this._size(), this.uiDialog.is(":data(resizable)") && this.uiDialog.resizable("option", s) + }, _setOption: function (t, r) { + var i, s, o = this.uiDialog; + switch (t) { + case"buttons": + this._createButtons(r); + break; + case"closeText": + this.uiDialogTitlebarCloseText.text("" + r); + break; + case"dialogClass": + o.removeClass(this.options.dialogClass).addClass(n + r); + break; + case"disabled": + r ? o.addClass("ui-dialog-disabled") : o.removeClass("ui-dialog-disabled"); + break; + case"draggable": + i = o.is(":data(draggable)"), i && !r && o.draggable("destroy"), !i && r && this._makeDraggable(); + break; + case"position": + this._position(r); + break; + case"resizable": + s = o.is(":data(resizable)"), s && !r && o.resizable("destroy"), s && typeof r == "string" && o.resizable("option", "handles", r), !s && r !== !1 && this._makeResizable(r); + break; + case"title": + e(".ui-dialog-title", this.uiDialogTitlebar).html("" + (r || " ")) + } + this._super(t, r) + }, _size: function () { + var t, n, r, i = this.options, s = this.uiDialog.is(":visible"); + this.element.show().css({width: "auto", minHeight: 0, height: 0}), i.minWidth > i.width && (i.width = i.minWidth), t = this.uiDialog.css({height: "auto", width: i.width}).outerHeight(), n = Math.max(0, i.minHeight - t), i.height === "auto" ? e.support.minHeight ? this.element.css({minHeight: n, height: "auto"}) : (this.uiDialog.show(), r = this.element.css("height", "auto").height(), s || this.uiDialog.hide(), this.element.height(Math.max(r, n))) : this.element.height(Math.max(i.height - t, 0)), this.uiDialog.is(":data(resizable)") && this.uiDialog.resizable("option", "minHeight", this._minHeight()) + }}), e.extend(e.ui.dialog, {uuid: 0, maxZ: 0, getTitleId: function (e) { + var t = e.attr("id"); + return t || (this.uuid += 1, t = this.uuid), "ui-dialog-title-" + t + }, overlay: function (t) { + this.$el = e.ui.dialog.overlay.create(t) + }}), e.extend(e.ui.dialog.overlay, {instances: [], oldInstances: [], maxZ: 0, events: e.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function (e) { + return e + ".dialog-overlay" + }).join(" "), create: function (t) { + this.instances.length === 0 && (setTimeout(function () { + e.ui.dialog.overlay.instances.length && e(document).bind(e.ui.dialog.overlay.events, function (t) { + if (e(t.target).zIndex() < e.ui.dialog.overlay.maxZ)return!1 + }) + }, 1), e(window).bind("resize.dialog-overlay", e.ui.dialog.overlay.resize)); + var n = this.oldInstances.pop() || e("
").addClass("ui-widget-overlay"); + return e(document).bind("keydown.dialog-overlay", function (r) { + var i = e.ui.dialog.overlay.instances; + i.length !== 0 && i[i.length - 1] === n && t.options.closeOnEscape && !r.isDefaultPrevented() && r.keyCode && r.keyCode === e.ui.keyCode.ESCAPE && (t.close(r), r.preventDefault()) + }), n.appendTo(document.body).css({width: this.width(), height: this.height()}), e.fn.bgiframe && n.bgiframe(), this.instances.push(n), n + }, destroy: function (t) { + var n = e.inArray(t, this.instances), r = 0; + n !== -1 && this.oldInstances.push(this.instances.splice(n, 1)[0]), this.instances.length === 0 && e([document, window]).unbind(".dialog-overlay"), t.height(0).width(0).remove(), e.each(this.instances, function () { + r = Math.max(r, this.css("z-index")) + }), this.maxZ = r + }, height: function () { + var t, n; + return e.ui.ie ? (t = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight), n = Math.max(document.documentElement.offsetHeight, document.body.offsetHeight), t < n ? e(window).height() + "px" : t + "px") : e(document).height() + "px" + }, width: function () { + var t, n; + return e.ui.ie ? (t = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth), n = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth), t < n ? e(window).width() + "px" : t + "px") : e(document).width() + "px" + }, resize: function () { + var t = e([]); + e.each(e.ui.dialog.overlay.instances, function () { + t = t.add(this) + }), t.css({width: 0, height: 0}).css({width: e.ui.dialog.overlay.width(), height: e.ui.dialog.overlay.height()}) + }}), e.extend(e.ui.dialog.overlay.prototype, {destroy: function () { + e.ui.dialog.overlay.destroy(this.$el) + }}) +})(jQuery); +(function (e, t) { + e.widget("ui.draggable", e.ui.mouse, {version: "1.9.1", widgetEventPrefix: "drag", options: {addClasses: !0, appendTo: "parent", axis: !1, connectToSortable: !1, containment: !1, cursor: "auto", cursorAt: !1, grid: !1, handle: !1, helper: "original", iframeFix: !1, opacity: !1, refreshPositions: !1, revert: !1, revertDuration: 500, scope: "default", scroll: !0, scrollSensitivity: 20, scrollSpeed: 20, snap: !1, snapMode: "both", snapTolerance: 20, stack: !1, zIndex: !1}, _create: function () { + this.options.helper == "original" && !/^(?:r|a|f)/.test(this.element.css("position")) && (this.element[0].style.position = "relative"), this.options.addClasses && this.element.addClass("ui-draggable"), this.options.disabled && this.element.addClass("ui-draggable-disabled"), this._mouseInit() + }, _destroy: function () { + this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"), this._mouseDestroy() + }, _mouseCapture: function (t) { + var n = this.options; + return this.helper || n.disabled || e(t.target).is(".ui-resizable-handle") ? !1 : (this.handle = this._getHandle(t), this.handle ? (e(n.iframeFix === !0 ? "iframe" : n.iframeFix).each(function () { + e('
').css({width: this.offsetWidth + "px", height: this.offsetHeight + "px", position: "absolute", opacity: "0.001", zIndex: 1e3}).css(e(this).offset()).appendTo("body") + }), !0) : !1) + }, _mouseStart: function (t) { + var n = this.options; + return this.helper = this._createHelper(t), this.helper.addClass("ui-draggable-dragging"), this._cacheHelperProportions(), e.ui.ddmanager && (e.ui.ddmanager.current = this), this._cacheMargins(), this.cssPosition = this.helper.css("position"), this.scrollParent = this.helper.scrollParent(), this.offset = this.positionAbs = this.element.offset(), this.offset = {top: this.offset.top - this.margins.top, left: this.offset.left - this.margins.left}, e.extend(this.offset, {click: {left: t.pageX - this.offset.left, top: t.pageY - this.offset.top}, parent: this._getParentOffset(), relative: this._getRelativeOffset()}), this.originalPosition = this.position = this._generatePosition(t), this.originalPageX = t.pageX, this.originalPageY = t.pageY, n.cursorAt && this._adjustOffsetFromHelper(n.cursorAt), n.containment && this._setContainment(), this._trigger("start", t) === !1 ? (this._clear(), !1) : (this._cacheHelperProportions(), e.ui.ddmanager && !n.dropBehaviour && e.ui.ddmanager.prepareOffsets(this, t), this._mouseDrag(t, !0), e.ui.ddmanager && e.ui.ddmanager.dragStart(this, t), !0) + }, _mouseDrag: function (t, n) { + this.position = this._generatePosition(t), this.positionAbs = this._convertPositionTo("absolute"); + if (!n) { + var r = this._uiHash(); + if (this._trigger("drag", t, r) === !1)return this._mouseUp({}), !1; + this.position = r.position + } + if (!this.options.axis || this.options.axis != "y")this.helper[0].style.left = this.position.left + "px"; + if (!this.options.axis || this.options.axis != "x")this.helper[0].style.top = this.position.top + "px"; + return e.ui.ddmanager && e.ui.ddmanager.drag(this, t), !1 + }, _mouseStop: function (t) { + var n = !1; + e.ui.ddmanager && !this.options.dropBehaviour && (n = e.ui.ddmanager.drop(this, t)), this.dropped && (n = this.dropped, this.dropped = !1); + var r = this.element[0], i = !1; + while (r && (r = r.parentNode))r == document && (i = !0); + if (!i && this.options.helper === "original")return!1; + if (this.options.revert == "invalid" && !n || this.options.revert == "valid" && n || this.options.revert === !0 || e.isFunction(this.options.revert) && this.options.revert.call(this.element, n)) { + var s = this; + e(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function () { + s._trigger("stop", t) !== !1 && s._clear() + }) + } else this._trigger("stop", t) !== !1 && this._clear(); + return!1 + }, _mouseUp: function (t) { + return e("div.ui-draggable-iframeFix").each(function () { + this.parentNode.removeChild(this) + }), e.ui.ddmanager && e.ui.ddmanager.dragStop(this, t), e.ui.mouse.prototype._mouseUp.call(this, t) + }, cancel: function () { + return this.helper.is(".ui-draggable-dragging") ? this._mouseUp({}) : this._clear(), this + }, _getHandle: function (t) { + var n = !this.options.handle || !e(this.options.handle, this.element).length ? !0 : !1; + return e(this.options.handle, this.element).find("*").andSelf().each(function () { + this == t.target && (n = !0) + }), n + }, _createHelper: function (t) { + var n = this.options, r = e.isFunction(n.helper) ? e(n.helper.apply(this.element[0], [t])) : n.helper == "clone" ? this.element.clone().removeAttr("id") : this.element; + return r.parents("body").length || r.appendTo(n.appendTo == "parent" ? this.element[0].parentNode : n.appendTo), r[0] != this.element[0] && !/(fixed|absolute)/.test(r.css("position")) && r.css("position", "absolute"), r + }, _adjustOffsetFromHelper: function (t) { + typeof t == "string" && (t = t.split(" ")), e.isArray(t) && (t = {left: +t[0], top: +t[1] || 0}), "left"in t && (this.offset.click.left = t.left + this.margins.left), "right"in t && (this.offset.click.left = this.helperProportions.width - t.right + this.margins.left), "top"in t && (this.offset.click.top = t.top + this.margins.top), "bottom"in t && (this.offset.click.top = this.helperProportions.height - t.bottom + this.margins.top) + }, _getParentOffset: function () { + this.offsetParent = this.helper.offsetParent(); + var t = this.offsetParent.offset(); + this.cssPosition == "absolute" && this.scrollParent[0] != document && e.contains(this.scrollParent[0], this.offsetParent[0]) && (t.left += this.scrollParent.scrollLeft(), t.top += this.scrollParent.scrollTop()); + if (this.offsetParent[0] == document.body || this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == "html" && e.ui.ie)t = {top: 0, left: 0}; + return{top: t.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), left: t.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)} + }, _getRelativeOffset: function () { + if (this.cssPosition == "relative") { + var e = this.element.position(); + return{top: e.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(), left: e.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft()} + } + return{top: 0, left: 0} + }, _cacheMargins: function () { + this.margins = {left: parseInt(this.element.css("marginLeft"), 10) || 0, top: parseInt(this.element.css("marginTop"), 10) || 0, right: parseInt(this.element.css("marginRight"), 10) || 0, bottom: parseInt(this.element.css("marginBottom"), 10) || 0} + }, _cacheHelperProportions: function () { + this.helperProportions = {width: this.helper.outerWidth(), height: this.helper.outerHeight()} + }, _setContainment: function () { + var t = this.options; + t.containment == "parent" && (t.containment = this.helper[0].parentNode); + if (t.containment == "document" || t.containment == "window")this.containment = [t.containment == "document" ? 0 : e(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, t.containment == "document" ? 0 : e(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, (t.containment == "document" ? 0 : e(window).scrollLeft()) + e(t.containment == "document" ? document : window).width() - this.helperProportions.width - this.margins.left, (t.containment == "document" ? 0 : e(window).scrollTop()) + (e(t.containment == "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top]; + if (!/^(document|window|parent)$/.test(t.containment) && t.containment.constructor != Array) { + var n = e(t.containment), r = n[0]; + if (!r)return; + var i = n.offset(), s = e(r).css("overflow") != "hidden"; + this.containment = [(parseInt(e(r).css("borderLeftWidth"), 10) || 0) + (parseInt(e(r).css("paddingLeft"), 10) || 0), (parseInt(e(r).css("borderTopWidth"), 10) || 0) + (parseInt(e(r).css("paddingTop"), 10) || 0), (s ? Math.max(r.scrollWidth, r.offsetWidth) : r.offsetWidth) - (parseInt(e(r).css("borderLeftWidth"), 10) || 0) - (parseInt(e(r).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, (s ? Math.max(r.scrollHeight, r.offsetHeight) : r.offsetHeight) - (parseInt(e(r).css("borderTopWidth"), 10) || 0) - (parseInt(e(r).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom], this.relative_container = n + } else t.containment.constructor == Array && (this.containment = t.containment) + }, _convertPositionTo: function (t, n) { + n || (n = this.position); + var r = t == "absolute" ? 1 : -1, i = this.options, s = this.cssPosition != "absolute" || this.scrollParent[0] != document && !!e.contains(this.scrollParent[0], this.offsetParent[0]) ? this.scrollParent : this.offsetParent, o = /(html|body)/i.test(s[0].tagName); + return{top: n.top + this.offset.relative.top * r + this.offset.parent.top * r - (this.cssPosition == "fixed" ? -this.scrollParent.scrollTop() : o ? 0 : s.scrollTop()) * r, left: n.left + this.offset.relative.left * r + this.offset.parent.left * r - (this.cssPosition == "fixed" ? -this.scrollParent.scrollLeft() : o ? 0 : s.scrollLeft()) * r} + }, _generatePosition: function (t) { + var n = this.options, r = this.cssPosition != "absolute" || this.scrollParent[0] != document && !!e.contains(this.scrollParent[0], this.offsetParent[0]) ? this.scrollParent : this.offsetParent, i = /(html|body)/i.test(r[0].tagName), s = t.pageX, o = t.pageY; + if (this.originalPosition) { + var u; + if (this.containment) { + if (this.relative_container) { + var a = this.relative_container.offset(); + u = [this.containment[0] + a.left, this.containment[1] + a.top, this.containment[2] + a.left, this.containment[3] + a.top] + } else u = this.containment; + t.pageX - this.offset.click.left < u[0] && (s = u[0] + this.offset.click.left), t.pageY - this.offset.click.top < u[1] && (o = u[1] + this.offset.click.top), t.pageX - this.offset.click.left > u[2] && (s = u[2] + this.offset.click.left), t.pageY - this.offset.click.top > u[3] && (o = u[3] + this.offset.click.top) + } + if (n.grid) { + var f = n.grid[1] ? this.originalPageY + Math.round((o - this.originalPageY) / n.grid[1]) * n.grid[1] : this.originalPageY; + o = u ? f - this.offset.click.top < u[1] || f - this.offset.click.top > u[3] ? f - this.offset.click.top < u[1] ? f + n.grid[1] : f - n.grid[1] : f : f; + var l = n.grid[0] ? this.originalPageX + Math.round((s - this.originalPageX) / n.grid[0]) * n.grid[0] : this.originalPageX; + s = u ? l - this.offset.click.left < u[0] || l - this.offset.click.left > u[2] ? l - this.offset.click.left < u[0] ? l + n.grid[0] : l - n.grid[0] : l : l + } + } + return{top: o - this.offset.click.top - this.offset.relative.top - this.offset.parent.top + (this.cssPosition == "fixed" ? -this.scrollParent.scrollTop() : i ? 0 : r.scrollTop()), left: s - this.offset.click.left - this.offset.relative.left - this.offset.parent.left + (this.cssPosition == "fixed" ? -this.scrollParent.scrollLeft() : i ? 0 : r.scrollLeft())} + }, _clear: function () { + this.helper.removeClass("ui-draggable-dragging"), this.helper[0] != this.element[0] && !this.cancelHelperRemoval && this.helper.remove(), this.helper = null, this.cancelHelperRemoval = !1 + }, _trigger: function (t, n, r) { + return r = r || this._uiHash(), e.ui.plugin.call(this, t, [n, r]), t == "drag" && (this.positionAbs = this._convertPositionTo("absolute")), e.Widget.prototype._trigger.call(this, t, n, r) + }, plugins: {}, _uiHash: function (e) { + return{helper: this.helper, position: this.position, originalPosition: this.originalPosition, offset: this.positionAbs} + }}), e.ui.plugin.add("draggable", "connectToSortable", {start: function (t, n) { + var r = e(this).data("draggable"), i = r.options, s = e.extend({}, n, {item: r.element}); + r.sortables = [], e(i.connectToSortable).each(function () { + var n = e.data(this, "sortable"); + n && !n.options.disabled && (r.sortables.push({instance: n, shouldRevert: n.options.revert}), n.refreshPositions(), n._trigger("activate", t, s)) + }) + }, stop: function (t, n) { + var r = e(this).data("draggable"), i = e.extend({}, n, {item: r.element}); + e.each(r.sortables, function () { + this.instance.isOver ? (this.instance.isOver = 0, r.cancelHelperRemoval = !0, this.instance.cancelHelperRemoval = !1, this.shouldRevert && (this.instance.options.revert = !0), this.instance._mouseStop(t), this.instance.options.helper = this.instance.options._helper, r.options.helper == "original" && this.instance.currentItem.css({top: "auto", left: "auto"})) : (this.instance.cancelHelperRemoval = !1, this.instance._trigger("deactivate", t, i)) + }) + }, drag: function (t, n) { + var r = e(this).data("draggable"), i = this, s = function (t) { + var n = this.offset.click.top, r = this.offset.click.left, i = this.positionAbs.top, s = this.positionAbs.left, o = t.height, u = t.width, a = t.top, f = t.left; + return e.ui.isOver(i + n, s + r, a, f, o, u) + }; + e.each(r.sortables, function (s) { + var o = !1, u = this; + this.instance.positionAbs = r.positionAbs, this.instance.helperProportions = r.helperProportions, this.instance.offset.click = r.offset.click, this.instance._intersectsWith(this.instance.containerCache) && (o = !0, e.each(r.sortables, function () { + return this.instance.positionAbs = r.positionAbs, this.instance.helperProportions = r.helperProportions, this.instance.offset.click = r.offset.click, this != u && this.instance._intersectsWith(this.instance.containerCache) && e.ui.contains(u.instance.element[0], this.instance.element[0]) && (o = !1), o + })), o ? (this.instance.isOver || (this.instance.isOver = 1, this.instance.currentItem = e(i).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item", !0), this.instance.options._helper = this.instance.options.helper, this.instance.options.helper = function () { + return n.helper[0] + }, t.target = this.instance.currentItem[0], this.instance._mouseCapture(t, !0), this.instance._mouseStart(t, !0, !0), this.instance.offset.click.top = r.offset.click.top, this.instance.offset.click.left = r.offset.click.left, this.instance.offset.parent.left -= r.offset.parent.left - this.instance.offset.parent.left, this.instance.offset.parent.top -= r.offset.parent.top - this.instance.offset.parent.top, r._trigger("toSortable", t), r.dropped = this.instance.element, r.currentItem = r.element, this.instance.fromOutside = r), this.instance.currentItem && this.instance._mouseDrag(t)) : this.instance.isOver && (this.instance.isOver = 0, this.instance.cancelHelperRemoval = !0, this.instance.options.revert = !1, this.instance._trigger("out", t, this.instance._uiHash(this.instance)), this.instance._mouseStop(t, !0), this.instance.options.helper = this.instance.options._helper, this.instance.currentItem.remove(), this.instance.placeholder && this.instance.placeholder.remove(), r._trigger("fromSortable", t), r.dropped = !1) + }) + }}), e.ui.plugin.add("draggable", "cursor", {start: function (t, n) { + var r = e("body"), i = e(this).data("draggable").options; + r.css("cursor") && (i._cursor = r.css("cursor")), r.css("cursor", i.cursor) + }, stop: function (t, n) { + var r = e(this).data("draggable").options; + r._cursor && e("body").css("cursor", r._cursor) + }}), e.ui.plugin.add("draggable", "opacity", {start: function (t, n) { + var r = e(n.helper), i = e(this).data("draggable").options; + r.css("opacity") && (i._opacity = r.css("opacity")), r.css("opacity", i.opacity) + }, stop: function (t, n) { + var r = e(this).data("draggable").options; + r._opacity && e(n.helper).css("opacity", r._opacity) + }}), e.ui.plugin.add("draggable", "scroll", {start: function (t, n) { + var r = e(this).data("draggable"); + r.scrollParent[0] != document && r.scrollParent[0].tagName != "HTML" && (r.overflowOffset = r.scrollParent.offset()) + }, drag: function (t, n) { + var r = e(this).data("draggable"), i = r.options, s = !1; + if (r.scrollParent[0] != document && r.scrollParent[0].tagName != "HTML") { + if (!i.axis || i.axis != "x")r.overflowOffset.top + r.scrollParent[0].offsetHeight - t.pageY < i.scrollSensitivity ? r.scrollParent[0].scrollTop = s = r.scrollParent[0].scrollTop + i.scrollSpeed : t.pageY - r.overflowOffset.top < i.scrollSensitivity && (r.scrollParent[0].scrollTop = s = r.scrollParent[0].scrollTop - i.scrollSpeed); + if (!i.axis || i.axis != "y")r.overflowOffset.left + r.scrollParent[0].offsetWidth - t.pageX < i.scrollSensitivity ? r.scrollParent[0].scrollLeft = s = r.scrollParent[0].scrollLeft + i.scrollSpeed : t.pageX - r.overflowOffset.left < i.scrollSensitivity && (r.scrollParent[0].scrollLeft = s = r.scrollParent[0].scrollLeft - i.scrollSpeed) + } else { + if (!i.axis || i.axis != "x")t.pageY - e(document).scrollTop() < i.scrollSensitivity ? s = e(document).scrollTop(e(document).scrollTop() - i.scrollSpeed) : e(window).height() - (t.pageY - e(document).scrollTop()) < i.scrollSensitivity && (s = e(document).scrollTop(e(document).scrollTop() + i.scrollSpeed)); + if (!i.axis || i.axis != "y")t.pageX - e(document).scrollLeft() < i.scrollSensitivity ? s = e(document).scrollLeft(e(document).scrollLeft() - i.scrollSpeed) : e(window).width() - (t.pageX - e(document).scrollLeft()) < i.scrollSensitivity && (s = e(document).scrollLeft(e(document).scrollLeft() + i.scrollSpeed)) + } + s !== !1 && e.ui.ddmanager && !i.dropBehaviour && e.ui.ddmanager.prepareOffsets(r, t) + }}), e.ui.plugin.add("draggable", "snap", {start: function (t, n) { + var r = e(this).data("draggable"), i = r.options; + r.snapElements = [], e(i.snap.constructor != String ? i.snap.items || ":data(draggable)" : i.snap).each(function () { + var t = e(this), n = t.offset(); + this != r.element[0] && r.snapElements.push({item: this, width: t.outerWidth(), height: t.outerHeight(), top: n.top, left: n.left}) + }) + }, drag: function (t, n) { + var r = e(this).data("draggable"), i = r.options, s = i.snapTolerance, o = n.offset.left, u = o + r.helperProportions.width, a = n.offset.top, f = a + r.helperProportions.height; + for (var l = r.snapElements.length - 1; l >= 0; l--) { + var c = r.snapElements[l].left, h = c + r.snapElements[l].width, p = r.snapElements[l].top, d = p + r.snapElements[l].height; + if (!(c - s < o && o < h + s && p - s < a && a < d + s || c - s < o && o < h + s && p - s < f && f < d + s || c - s < u && u < h + s && p - s < a && a < d + s || c - s < u && u < h + s && p - s < f && f < d + s)) { + r.snapElements[l].snapping && r.options.snap.release && r.options.snap.release.call(r.element, t, e.extend(r._uiHash(), {snapItem: r.snapElements[l].item})), r.snapElements[l].snapping = !1; + continue + } + if (i.snapMode != "inner") { + var v = Math.abs(p - f) <= s, m = Math.abs(d - a) <= s, g = Math.abs(c - u) <= s, y = Math.abs(h - o) <= s; + v && (n.position.top = r._convertPositionTo("relative", {top: p - r.helperProportions.height, left: 0}).top - r.margins.top), m && (n.position.top = r._convertPositionTo("relative", {top: d, left: 0}).top - r.margins.top), g && (n.position.left = r._convertPositionTo("relative", {top: 0, left: c - r.helperProportions.width}).left - r.margins.left), y && (n.position.left = r._convertPositionTo("relative", {top: 0, left: h}).left - r.margins.left) + } + var b = v || m || g || y; + if (i.snapMode != "outer") { + var v = Math.abs(p - a) <= s, m = Math.abs(d - f) <= s, g = Math.abs(c - o) <= s, y = Math.abs(h - u) <= s; + v && (n.position.top = r._convertPositionTo("relative", {top: p, left: 0}).top - r.margins.top), m && (n.position.top = r._convertPositionTo("relative", {top: d - r.helperProportions.height, left: 0}).top - r.margins.top), g && (n.position.left = r._convertPositionTo("relative", {top: 0, left: c}).left - r.margins.left), y && (n.position.left = r._convertPositionTo("relative", {top: 0, left: h - r.helperProportions.width}).left - r.margins.left) + } + !r.snapElements[l].snapping && (v || m || g || y || b) && r.options.snap.snap && r.options.snap.snap.call(r.element, t, e.extend(r._uiHash(), {snapItem: r.snapElements[l].item})), r.snapElements[l].snapping = v || m || g || y || b + } + }}), e.ui.plugin.add("draggable", "stack", {start: function (t, n) { + var r = e(this).data("draggable").options, i = e.makeArray(e(r.stack)).sort(function (t, n) { + return(parseInt(e(t).css("zIndex"), 10) || 0) - (parseInt(e(n).css("zIndex"), 10) || 0) + }); + if (!i.length)return; + var s = parseInt(i[0].style.zIndex) || 0; + e(i).each(function (e) { + this.style.zIndex = s + e + }), this[0].style.zIndex = s + i.length + }}), e.ui.plugin.add("draggable", "zIndex", {start: function (t, n) { + var r = e(n.helper), i = e(this).data("draggable").options; + r.css("zIndex") && (i._zIndex = r.css("zIndex")), r.css("zIndex", i.zIndex) + }, stop: function (t, n) { + var r = e(this).data("draggable").options; + r._zIndex && e(n.helper).css("zIndex", r._zIndex) + }}) +})(jQuery); +(function (e, t) { + e.widget("ui.droppable", {version: "1.9.1", widgetEventPrefix: "drop", options: {accept: "*", activeClass: !1, addClasses: !0, greedy: !1, hoverClass: !1, scope: "default", tolerance: "intersect"}, _create: function () { + var t = this.options, n = t.accept; + this.isover = 0, this.isout = 1, this.accept = e.isFunction(n) ? n : function (e) { + return e.is(n) + }, this.proportions = {width: this.element[0].offsetWidth, height: this.element[0].offsetHeight}, e.ui.ddmanager.droppables[t.scope] = e.ui.ddmanager.droppables[t.scope] || [], e.ui.ddmanager.droppables[t.scope].push(this), t.addClasses && this.element.addClass("ui-droppable") + }, _destroy: function () { + var t = e.ui.ddmanager.droppables[this.options.scope]; + for (var n = 0; n < t.length; n++)t[n] == this && t.splice(n, 1); + this.element.removeClass("ui-droppable ui-droppable-disabled") + }, _setOption: function (t, n) { + t == "accept" && (this.accept = e.isFunction(n) ? n : function (e) { + return e.is(n) + }), e.Widget.prototype._setOption.apply(this, arguments) + }, _activate: function (t) { + var n = e.ui.ddmanager.current; + this.options.activeClass && this.element.addClass(this.options.activeClass), n && this._trigger("activate", t, this.ui(n)) + }, _deactivate: function (t) { + var n = e.ui.ddmanager.current; + this.options.activeClass && this.element.removeClass(this.options.activeClass), n && this._trigger("deactivate", t, this.ui(n)) + }, _over: function (t) { + var n = e.ui.ddmanager.current; + if (!n || (n.currentItem || n.element)[0] == this.element[0])return; + this.accept.call(this.element[0], n.currentItem || n.element) && (this.options.hoverClass && this.element.addClass(this.options.hoverClass), this._trigger("over", t, this.ui(n))) + }, _out: function (t) { + var n = e.ui.ddmanager.current; + if (!n || (n.currentItem || n.element)[0] == this.element[0])return; + this.accept.call(this.element[0], n.currentItem || n.element) && (this.options.hoverClass && this.element.removeClass(this.options.hoverClass), this._trigger("out", t, this.ui(n))) + }, _drop: function (t, n) { + var r = n || e.ui.ddmanager.current; + if (!r || (r.currentItem || r.element)[0] == this.element[0])return!1; + var i = !1; + return this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function () { + var t = e.data(this, "droppable"); + if (t.options.greedy && !t.options.disabled && t.options.scope == r.options.scope && t.accept.call(t.element[0], r.currentItem || r.element) && e.ui.intersect(r, e.extend(t, {offset: t.element.offset()}), t.options.tolerance))return i = !0, !1 + }), i ? !1 : this.accept.call(this.element[0], r.currentItem || r.element) ? (this.options.activeClass && this.element.removeClass(this.options.activeClass), this.options.hoverClass && this.element.removeClass(this.options.hoverClass), this._trigger("drop", t, this.ui(r)), this.element) : !1 + }, ui: function (e) { + return{draggable: e.currentItem || e.element, helper: e.helper, position: e.position, offset: e.positionAbs} + }}), e.ui.intersect = function (t, n, r) { + if (!n.offset)return!1; + var i = (t.positionAbs || t.position.absolute).left, s = i + t.helperProportions.width, o = (t.positionAbs || t.position.absolute).top, u = o + t.helperProportions.height, a = n.offset.left, f = a + n.proportions.width, l = n.offset.top, c = l + n.proportions.height; + switch (r) { + case"fit": + return a <= i && s <= f && l <= o && u <= c; + case"intersect": + return a < i + t.helperProportions.width / 2 && s - t.helperProportions.width / 2 < f && l < o + t.helperProportions.height / 2 && u - t.helperProportions.height / 2 < c; + case"pointer": + var h = (t.positionAbs || t.position.absolute).left + (t.clickOffset || t.offset.click).left, p = (t.positionAbs || t.position.absolute).top + (t.clickOffset || t.offset.click).top, d = e.ui.isOver(p, h, l, a, n.proportions.height, n.proportions.width); + return d; + case"touch": + return(o >= l && o <= c || u >= l && u <= c || o < l && u > c) && (i >= a && i <= f || s >= a && s <= f || i < a && s > f); + default: + return!1 + } + }, e.ui.ddmanager = {current: null, droppables: {"default": []}, prepareOffsets: function (t, n) { + var r = e.ui.ddmanager.droppables[t.options.scope] || [], i = n ? n.type : null, s = (t.currentItem || t.element).find(":data(droppable)").andSelf(); + e:for (var o = 0; o < r.length; o++) { + if (r[o].options.disabled || t && !r[o].accept.call(r[o].element[0], t.currentItem || t.element))continue; + for (var u = 0; u < s.length; u++)if (s[u] == r[o].element[0]) { + r[o].proportions.height = 0; + continue e + } + r[o].visible = r[o].element.css("display") != "none"; + if (!r[o].visible)continue; + i == "mousedown" && r[o]._activate.call(r[o], n), r[o].offset = r[o].element.offset(), r[o].proportions = {width: r[o].element[0].offsetWidth, height: r[o].element[0].offsetHeight} + } + }, drop: function (t, n) { + var r = !1; + return e.each(e.ui.ddmanager.droppables[t.options.scope] || [], function () { + if (!this.options)return; + !this.options.disabled && this.visible && e.ui.intersect(t, this, this.options.tolerance) && (r = this._drop.call(this, n) || r), !this.options.disabled && this.visible && this.accept.call(this.element[0], t.currentItem || t.element) && (this.isout = 1, this.isover = 0, this._deactivate.call(this, n)) + }), r + }, dragStart: function (t, n) { + t.element.parentsUntil("body").bind("scroll.droppable", function () { + t.options.refreshPositions || e.ui.ddmanager.prepareOffsets(t, n) + }) + }, drag: function (t, n) { + t.options.refreshPositions && e.ui.ddmanager.prepareOffsets(t, n), e.each(e.ui.ddmanager.droppables[t.options.scope] || [], function () { + if (this.options.disabled || this.greedyChild || !this.visible)return; + var r = e.ui.intersect(t, this, this.options.tolerance), i = !r && this.isover == 1 ? "isout" : r && this.isover == 0 ? "isover" : null; + if (!i)return; + var s; + if (this.options.greedy) { + var o = this.options.scope, u = this.element.parents(":data(droppable)").filter(function () { + return e.data(this, "droppable").options.scope === o + }); + u.length && (s = e.data(u[0], "droppable"), s.greedyChild = i == "isover" ? 1 : 0) + } + s && i == "isover" && (s.isover = 0, s.isout = 1, s._out.call(s, n)), this[i] = 1, this[i == "isout" ? "isover" : "isout"] = 0, this[i == "isover" ? "_over" : "_out"].call(this, n), s && i == "isout" && (s.isout = 0, s.isover = 1, s._over.call(s, n)) + }) + }, dragStop: function (t, n) { + t.element.parentsUntil("body").unbind("scroll.droppable"), t.options.refreshPositions || e.ui.ddmanager.prepareOffsets(t, n) + }} +})(jQuery); +jQuery.effects || function (e, t) { + var n = e.uiBackCompat !== !1, r = "ui-effects-"; + e.effects = {effect: {}}, function (t, n) { + function p(e, t, n) { + var r = a[t.type] || {}; + return e == null ? n || !t.def ? null : t.def : (e = r.floor ? ~~e : parseFloat(e), isNaN(e) ? t.def : r.mod ? (e + r.mod) % r.mod : 0 > e ? 0 : r.max < e ? r.max : e) + } + + function d(e) { + var n = o(), r = n._rgba = []; + return e = e.toLowerCase(), h(s, function (t, i) { + var s, o = i.re.exec(e), a = o && i.parse(o), f = i.space || "rgba"; + if (a)return s = n[f](a), n[u[f].cache] = s[u[f].cache], r = n._rgba = s._rgba, !1 + }), r.length ? (r.join() === "0,0,0,0" && t.extend(r, c.transparent), n) : c[e] + } + + function v(e, t, n) { + return n = (n + 1) % 1, n * 6 < 1 ? e + (t - e) * n * 6 : n * 2 < 1 ? t : n * 3 < 2 ? e + (t - e) * (2 / 3 - n) * 6 : e + } + + var r = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "), i = /^([\-+])=\s*(\d+\.?\d*)/, s = [ + {re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, parse: function (e) { + return[e[1], e[2], e[3], e[4]] + }}, + {re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, parse: function (e) { + return[e[1] * 2.55, e[2] * 2.55, e[3] * 2.55, e[4]] + }}, + {re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, parse: function (e) { + return[parseInt(e[1], 16), parseInt(e[2], 16), parseInt(e[3], 16)] + }}, + {re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, parse: function (e) { + return[parseInt(e[1] + e[1], 16), parseInt(e[2] + e[2], 16), parseInt(e[3] + e[3], 16)] + }}, + {re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, space: "hsla", parse: function (e) { + return[e[1], e[2] / 100, e[3] / 100, e[4]] + }} + ], o = t.Color = function (e, n, r, i) { + return new t.Color.fn.parse(e, n, r, i) + }, u = {rgba: {props: {red: {idx: 0, type: "byte"}, green: {idx: 1, type: "byte"}, blue: {idx: 2, type: "byte"}}}, hsla: {props: {hue: {idx: 0, type: "degrees"}, saturation: {idx: 1, type: "percent"}, lightness: {idx: 2, type: "percent"}}}}, a = {"byte": {floor: !0, max: 255}, percent: {max: 1}, degrees: {mod: 360, floor: !0}}, f = o.support = {}, l = t("

")[0], c, h = t.each; + l.style.cssText = "background-color:rgba(1,1,1,.5)", f.rgba = l.style.backgroundColor.indexOf("rgba") > -1, h(u, function (e, t) { + t.cache = "_" + e, t.props.alpha = {idx: 3, type: "percent", def: 1} + }), o.fn = t.extend(o.prototype, {parse: function (r, i, s, a) { + if (r === n)return this._rgba = [null, null, null, null], this; + if (r.jquery || r.nodeType)r = t(r).css(i), i = n; + var f = this, l = t.type(r), v = this._rgba = []; + i !== n && (r = [r, i, s, a], l = "array"); + if (l === "string")return this.parse(d(r) || c._default); + if (l === "array")return h(u.rgba.props, function (e, t) { + v[t.idx] = p(r[t.idx], t) + }), this; + if (l === "object")return r instanceof o ? h(u, function (e, t) { + r[t.cache] && (f[t.cache] = r[t.cache].slice()) + }) : h(u, function (t, n) { + var i = n.cache; + h(n.props, function (e, t) { + if (!f[i] && n.to) { + if (e === "alpha" || r[e] == null)return; + f[i] = n.to(f._rgba) + } + f[i][t.idx] = p(r[e], t, !0) + }), f[i] && e.inArray(null, f[i].slice(0, 3)) < 0 && (f[i][3] = 1, n.from && (f._rgba = n.from(f[i]))) + }), this + }, is: function (e) { + var t = o(e), n = !0, r = this; + return h(u, function (e, i) { + var s, o = t[i.cache]; + return o && (s = r[i.cache] || i.to && i.to(r._rgba) || [], h(i.props, function (e, t) { + if (o[t.idx] != null)return n = o[t.idx] === s[t.idx], n + })), n + }), n + }, _space: function () { + var e = [], t = this; + return h(u, function (n, r) { + t[r.cache] && e.push(n) + }), e.pop() + }, transition: function (e, t) { + var n = o(e), r = n._space(), i = u[r], s = this.alpha() === 0 ? o("transparent") : this, f = s[i.cache] || i.to(s._rgba), l = f.slice(); + return n = n[i.cache], h(i.props, function (e, r) { + var i = r.idx, s = f[i], o = n[i], u = a[r.type] || {}; + if (o === null)return; + s === null ? l[i] = o : (u.mod && (o - s > u.mod / 2 ? s += u.mod : s - o > u.mod / 2 && (s -= u.mod)), l[i] = p((o - s) * t + s, r)) + }), this[r](l) + }, blend: function (e) { + if (this._rgba[3] === 1)return this; + var n = this._rgba.slice(), r = n.pop(), i = o(e)._rgba; + return o(t.map(n, function (e, t) { + return(1 - r) * i[t] + r * e + })) + }, toRgbaString: function () { + var e = "rgba(", n = t.map(this._rgba, function (e, t) { + return e == null ? t > 2 ? 1 : 0 : e + }); + return n[3] === 1 && (n.pop(), e = "rgb("), e + n.join() + ")" + }, toHslaString: function () { + var e = "hsla(", n = t.map(this.hsla(), function (e, t) { + return e == null && (e = t > 2 ? 1 : 0), t && t < 3 && (e = Math.round(e * 100) + "%"), e + }); + return n[3] === 1 && (n.pop(), e = "hsl("), e + n.join() + ")" + }, toHexString: function (e) { + var n = this._rgba.slice(), r = n.pop(); + return e && n.push(~~(r * 255)), "#" + t.map(n,function (e) { + return e = (e || 0).toString(16), e.length === 1 ? "0" + e : e + }).join("") + }, toString: function () { + return this._rgba[3] === 0 ? "transparent" : this.toRgbaString() + }}), o.fn.parse.prototype = o.fn, u.hsla.to = function (e) { + if (e[0] == null || e[1] == null || e[2] == null)return[null, null, null, e[3]]; + var t = e[0] / 255, n = e[1] / 255, r = e[2] / 255, i = e[3], s = Math.max(t, n, r), o = Math.min(t, n, r), u = s - o, a = s + o, f = a * .5, l, c; + return o === s ? l = 0 : t === s ? l = 60 * (n - r) / u + 360 : n === s ? l = 60 * (r - t) / u + 120 : l = 60 * (t - n) / u + 240, f === 0 || f === 1 ? c = f : f <= .5 ? c = u / a : c = u / (2 - a), [Math.round(l) % 360, c, f, i == null ? 1 : i] + }, u.hsla.from = function (e) { + if (e[0] == null || e[1] == null || e[2] == null)return[null, null, null, e[3]]; + var t = e[0] / 360, n = e[1], r = e[2], i = e[3], s = r <= .5 ? r * (1 + n) : r + n - r * n, o = 2 * r - s; + return[Math.round(v(o, s, t + 1 / 3) * 255), Math.round(v(o, s, t) * 255), Math.round(v(o, s, t - 1 / 3) * 255), i] + }, h(u, function (e, r) { + var s = r.props, u = r.cache, a = r.to, f = r.from; + o.fn[e] = function (e) { + a && !this[u] && (this[u] = a(this._rgba)); + if (e === n)return this[u].slice(); + var r, i = t.type(e), l = i === "array" || i === "object" ? e : arguments, c = this[u].slice(); + return h(s, function (e, t) { + var n = l[i === "object" ? e : t.idx]; + n == null && (n = c[t.idx]), c[t.idx] = p(n, t) + }), f ? (r = o(f(c)), r[u] = c, r) : o(c) + }, h(s, function (n, r) { + if (o.fn[n])return; + o.fn[n] = function (s) { + var o = t.type(s), u = n === "alpha" ? this._hsla ? "hsla" : "rgba" : e, a = this[u](), f = a[r.idx], l; + return o === "undefined" ? f : (o === "function" && (s = s.call(this, f), o = t.type(s)), s == null && r.empty ? this : (o === "string" && (l = i.exec(s), l && (s = f + parseFloat(l[2]) * (l[1] === "+" ? 1 : -1))), a[r.idx] = s, this[u](a))) + } + }) + }), h(r, function (e, n) { + t.cssHooks[n] = {set: function (e, r) { + var i, s, u = ""; + if (t.type(r) !== "string" || (i = d(r))) { + r = o(i || r); + if (!f.rgba && r._rgba[3] !== 1) { + s = n === "backgroundColor" ? e.parentNode : e; + while ((u === "" || u === "transparent") && s && s.style)try { + u = t.css(s, "backgroundColor"), s = s.parentNode + } catch (a) { + } + r = r.blend(u && u !== "transparent" ? u : "_default") + } + r = r.toRgbaString() + } + try { + e.style[n] = r + } catch (l) { + } + }}, t.fx.step[n] = function (e) { + e.colorInit || (e.start = o(e.elem, n), e.end = o(e.end), e.colorInit = !0), t.cssHooks[n].set(e.elem, e.start.transition(e.end, e.pos)) + } + }), t.cssHooks.borderColor = {expand: function (e) { + var t = {}; + return h(["Top", "Right", "Bottom", "Left"], function (n, r) { + t["border" + r + "Color"] = e + }), t + }}, c = t.Color.names = {aqua: "#00ffff", black: "#000000", blue: "#0000ff", fuchsia: "#ff00ff", gray: "#808080", green: "#008000", lime: "#00ff00", maroon: "#800000", navy: "#000080", olive: "#808000", purple: "#800080", red: "#ff0000", silver: "#c0c0c0", teal: "#008080", white: "#ffffff", yellow: "#ffff00", transparent: [null, null, null, 0], _default: "#ffffff"} + }(jQuery), function () { + function i() { + var t = this.ownerDocument.defaultView ? this.ownerDocument.defaultView.getComputedStyle(this, null) : this.currentStyle, n = {}, r, i; + if (t && t.length && t[0] && t[t[0]]) { + i = t.length; + while (i--)r = t[i], typeof t[r] == "string" && (n[e.camelCase(r)] = t[r]) + } else for (r in t)typeof t[r] == "string" && (n[r] = t[r]); + return n + } + + function s(t, n) { + var i = {}, s, o; + for (s in n)o = n[s], t[s] !== o && !r[s] && (e.fx.step[s] || !isNaN(parseFloat(o))) && (i[s] = o); + return i + } + + var n = ["add", "remove", "toggle"], r = {border: 1, borderBottom: 1, borderColor: 1, borderLeft: 1, borderRight: 1, borderTop: 1, borderWidth: 1, margin: 1, padding: 1}; + e.each(["borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle"], function (t, n) { + e.fx.step[n] = function (e) { + if (e.end !== "none" && !e.setAttr || e.pos === 1 && !e.setAttr)jQuery.style(e.elem, n, e.end), e.setAttr = !0 + } + }), e.effects.animateClass = function (t, r, o, u) { + var a = e.speed(r, o, u); + return this.queue(function () { + var r = e(this), o = r.attr("class") || "", u, f = a.children ? r.find("*").andSelf() : r; + f = f.map(function () { + var t = e(this); + return{el: t, start: i.call(this)} + }), u = function () { + e.each(n, function (e, n) { + t[n] && r[n + "Class"](t[n]) + }) + }, u(), f = f.map(function () { + return this.end = i.call(this.el[0]), this.diff = s(this.start, this.end), this + }), r.attr("class", o), f = f.map(function () { + var t = this, n = e.Deferred(), r = jQuery.extend({}, a, {queue: !1, complete: function () { + n.resolve(t) + }}); + return this.el.animate(this.diff, r), n.promise() + }), e.when.apply(e, f.get()).done(function () { + u(), e.each(arguments, function () { + var t = this.el; + e.each(this.diff, function (e) { + t.css(e, "") + }) + }), a.complete.call(r[0]) + }) + }) + }, e.fn.extend({_addClass: e.fn.addClass, addClass: function (t, n, r, i) { + return n ? e.effects.animateClass.call(this, {add: t}, n, r, i) : this._addClass(t) + }, _removeClass: e.fn.removeClass, removeClass: function (t, n, r, i) { + return n ? e.effects.animateClass.call(this, {remove: t}, n, r, i) : this._removeClass(t) + }, _toggleClass: e.fn.toggleClass, toggleClass: function (n, r, i, s, o) { + return typeof r == "boolean" || r === t ? i ? e.effects.animateClass.call(this, r ? {add: n} : {remove: n}, i, s, o) : this._toggleClass(n, r) : e.effects.animateClass.call(this, {toggle: n}, r, i, s) + }, switchClass: function (t, n, r, i, s) { + return e.effects.animateClass.call(this, {add: n, remove: t}, r, i, s) + }}) + }(), function () { + function i(t, n, r, i) { + e.isPlainObject(t) && (n = t, t = t.effect), t = {effect: t}, n == null && (n = {}), e.isFunction(n) && (i = n, r = null, n = {}); + if (typeof n == "number" || e.fx.speeds[n])i = r, r = n, n = {}; + return e.isFunction(r) && (i = r, r = null), n && e.extend(t, n), r = r || n.duration, t.duration = e.fx.off ? 0 : typeof r == "number" ? r : r in e.fx.speeds ? e.fx.speeds[r] : e.fx.speeds._default, t.complete = i || n.complete, t + } + + function s(t) { + return!t || typeof t == "number" || e.fx.speeds[t] ? !0 : typeof t == "string" && !e.effects.effect[t] ? n && e.effects[t] ? !1 : !0 : !1 + } + + e.extend(e.effects, {version: "1.9.1", save: function (e, t) { + for (var n = 0; n < t.length; n++)t[n] !== null && e.data(r + t[n], e[0].style[t[n]]) + }, restore: function (e, n) { + var i, s; + for (s = 0; s < n.length; s++)n[s] !== null && (i = e.data(r + n[s]), i === t && (i = ""), e.css(n[s], i)) + }, setMode: function (e, t) { + return t === "toggle" && (t = e.is(":hidden") ? "show" : "hide"), t + }, getBaseline: function (e, t) { + var n, r; + switch (e[0]) { + case"top": + n = 0; + break; + case"middle": + n = .5; + break; + case"bottom": + n = 1; + break; + default: + n = e[0] / t.height + } + switch (e[1]) { + case"left": + r = 0; + break; + case"center": + r = .5; + break; + case"right": + r = 1; + break; + default: + r = e[1] / t.width + } + return{x: r, y: n} + }, createWrapper: function (t) { + if (t.parent().is(".ui-effects-wrapper"))return t.parent(); + var n = {width: t.outerWidth(!0), height: t.outerHeight(!0), "float": t.css("float")}, r = e("

").addClass("ui-effects-wrapper").css({fontSize: "100%", background: "transparent", border: "none", margin: 0, padding: 0}), i = {width: t.width(), height: t.height()}, s = document.activeElement; + try { + s.id + } catch (o) { + s = document.body + } + return t.wrap(r), (t[0] === s || e.contains(t[0], s)) && e(s).focus(), r = t.parent(), t.css("position") === "static" ? (r.css({position: "relative"}), t.css({position: "relative"})) : (e.extend(n, {position: t.css("position"), zIndex: t.css("z-index")}), e.each(["top", "left", "bottom", "right"], function (e, r) { + n[r] = t.css(r), isNaN(parseInt(n[r], 10)) && (n[r] = "auto") + }), t.css({position: "relative", top: 0, left: 0, right: "auto", bottom: "auto"})), t.css(i), r.css(n).show() + }, removeWrapper: function (t) { + var n = document.activeElement; + return t.parent().is(".ui-effects-wrapper") && (t.parent().replaceWith(t), (t[0] === n || e.contains(t[0], n)) && e(n).focus()), t + }, setTransition: function (t, n, r, i) { + return i = i || {}, e.each(n, function (e, n) { + var s = t.cssUnit(n); + s[0] > 0 && (i[n] = s[0] * r + s[1]) + }), i + }}), e.fn.extend({effect: function () { + function a(n) { + function u() { + e.isFunction(i) && i.call(r[0]), e.isFunction(n) && n() + } + + var r = e(this), i = t.complete, s = t.mode; + (r.is(":hidden") ? s === "hide" : s === "show") ? u() : o.call(r[0], t, u) + } + + var t = i.apply(this, arguments), r = t.mode, s = t.queue, o = e.effects.effect[t.effect], u = !o && n && e.effects[t.effect]; + return e.fx.off || !o && !u ? r ? this[r](t.duration, t.complete) : this.each(function () { + t.complete && t.complete.call(this) + }) : o ? s === !1 ? this.each(a) : this.queue(s || "fx", a) : u.call(this, {options: t, duration: t.duration, callback: t.complete, mode: t.mode}) + }, _show: e.fn.show, show: function (e) { + if (s(e))return this._show.apply(this, arguments); + var t = i.apply(this, arguments); + return t.mode = "show", this.effect.call(this, t) + }, _hide: e.fn.hide, hide: function (e) { + if (s(e))return this._hide.apply(this, arguments); + var t = i.apply(this, arguments); + return t.mode = "hide", this.effect.call(this, t) + }, __toggle: e.fn.toggle, toggle: function (t) { + if (s(t) || typeof t == "boolean" || e.isFunction(t))return this.__toggle.apply(this, arguments); + var n = i.apply(this, arguments); + return n.mode = "toggle", this.effect.call(this, n) + }, cssUnit: function (t) { + var n = this.css(t), r = []; + return e.each(["em", "px", "%", "pt"], function (e, t) { + n.indexOf(t) > 0 && (r = [parseFloat(n), t]) + }), r + }}) + }(), function () { + var t = {}; + e.each(["Quad", "Cubic", "Quart", "Quint", "Expo"], function (e, n) { + t[n] = function (t) { + return Math.pow(t, e + 2) + } + }), e.extend(t, {Sine: function (e) { + return 1 - Math.cos(e * Math.PI / 2) + }, Circ: function (e) { + return 1 - Math.sqrt(1 - e * e) + }, Elastic: function (e) { + return e === 0 || e === 1 ? e : -Math.pow(2, 8 * (e - 1)) * Math.sin(((e - 1) * 80 - 7.5) * Math.PI / 15) + }, Back: function (e) { + return e * e * (3 * e - 2) + }, Bounce: function (e) { + var t, n = 4; + while (e < ((t = Math.pow(2, --n)) - 1) / 11); + return 1 / Math.pow(4, 3 - n) - 7.5625 * Math.pow((t * 3 - 2) / 22 - e, 2) + }}), e.each(t, function (t, n) { + e.easing["easeIn" + t] = n, e.easing["easeOut" + t] = function (e) { + return 1 - n(1 - e) + }, e.easing["easeInOut" + t] = function (e) { + return e < .5 ? n(e * 2) / 2 : 1 - n(e * -2 + 2) / 2 + } + }) + }() +}(jQuery); +(function (e, t) { + var n = /up|down|vertical/, r = /up|left|vertical|horizontal/; + e.effects.effect.blind = function (t, i) { + var s = e(this), o = ["position", "top", "bottom", "left", "right", "height", "width"], u = e.effects.setMode(s, t.mode || "hide"), a = t.direction || "up", f = n.test(a), l = f ? "height" : "width", c = f ? "top" : "left", h = r.test(a), p = {}, d = u === "show", v, m, g; + s.parent().is(".ui-effects-wrapper") ? e.effects.save(s.parent(), o) : e.effects.save(s, o), s.show(), v = e.effects.createWrapper(s).css({overflow: "hidden"}), m = v[l](), g = parseFloat(v.css(c)) || 0, p[l] = d ? m : 0, h || (s.css(f ? "bottom" : "right", 0).css(f ? "top" : "left", "auto").css({position: "absolute"}), p[c] = d ? g : m + g), d && (v.css(l, 0), h || v.css(c, g + m)), v.animate(p, {duration: t.duration, easing: t.easing, queue: !1, complete: function () { + u === "hide" && s.hide(), e.effects.restore(s, o), e.effects.removeWrapper(s), i() + }}) + } +})(jQuery); +(function (e, t) { + e.effects.effect.bounce = function (t, n) { + var r = e(this), i = ["position", "top", "bottom", "left", "right", "height", "width"], s = e.effects.setMode(r, t.mode || "effect"), o = s === "hide", u = s === "show", a = t.direction || "up", f = t.distance, l = t.times || 5, c = l * 2 + (u || o ? 1 : 0), h = t.duration / c, p = t.easing, d = a === "up" || a === "down" ? "top" : "left", v = a === "up" || a === "left", m, g, y, b = r.queue(), w = b.length; + (u || o) && i.push("opacity"), e.effects.save(r, i), r.show(), e.effects.createWrapper(r), f || (f = r[d === "top" ? "outerHeight" : "outerWidth"]() / 3), u && (y = {opacity: 1}, y[d] = 0, r.css("opacity", 0).css(d, v ? -f * 2 : f * 2).animate(y, h, p)), o && (f /= Math.pow(2, l - 1)), y = {}, y[d] = 0; + for (m = 0; m < l; m++)g = {}, g[d] = (v ? "-=" : "+=") + f, r.animate(g, h, p).animate(y, h, p), f = o ? f * 2 : f / 2; + o && (g = {opacity: 0}, g[d] = (v ? "-=" : "+=") + f, r.animate(g, h, p)), r.queue(function () { + o && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n() + }), w > 1 && b.splice.apply(b, [1, 0].concat(b.splice(w, c + 1))), r.dequeue() + } +})(jQuery); +(function (e, t) { + e.effects.effect.clip = function (t, n) { + var r = e(this), i = ["position", "top", "bottom", "left", "right", "height", "width"], s = e.effects.setMode(r, t.mode || "hide"), o = s === "show", u = t.direction || "vertical", a = u === "vertical", f = a ? "height" : "width", l = a ? "top" : "left", c = {}, h, p, d; + e.effects.save(r, i), r.show(), h = e.effects.createWrapper(r).css({overflow: "hidden"}), p = r[0].tagName === "IMG" ? h : r, d = p[f](), o && (p.css(f, 0), p.css(l, d / 2)), c[f] = o ? d : 0, c[l] = o ? 0 : d / 2, p.animate(c, {queue: !1, duration: t.duration, easing: t.easing, complete: function () { + o || r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n() + }}) + } +})(jQuery); +(function (e, t) { + e.effects.effect.drop = function (t, n) { + var r = e(this), i = ["position", "top", "bottom", "left", "right", "opacity", "height", "width"], s = e.effects.setMode(r, t.mode || "hide"), o = s === "show", u = t.direction || "left", a = u === "up" || u === "down" ? "top" : "left", f = u === "up" || u === "left" ? "pos" : "neg", l = {opacity: o ? 1 : 0}, c; + e.effects.save(r, i), r.show(), e.effects.createWrapper(r), c = t.distance || r[a === "top" ? "outerHeight" : "outerWidth"](!0) / 2, o && r.css("opacity", 0).css(a, f === "pos" ? -c : c), l[a] = (o ? f === "pos" ? "+=" : "-=" : f === "pos" ? "-=" : "+=") + c, r.animate(l, {queue: !1, duration: t.duration, easing: t.easing, complete: function () { + s === "hide" && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n() + }}) + } +})(jQuery); +(function (e, t) { + e.effects.effect.explode = function (t, n) { + function y() { + c.push(this), c.length === r * i && b() + } + + function b() { + s.css({visibility: "visible"}), e(c).remove(), u || s.hide(), n() + } + + var r = t.pieces ? Math.round(Math.sqrt(t.pieces)) : 3, i = r, s = e(this), o = e.effects.setMode(s, t.mode || "hide"), u = o === "show", a = s.show().css("visibility", "hidden").offset(), f = Math.ceil(s.outerWidth() / i), l = Math.ceil(s.outerHeight() / r), c = [], h, p, d, v, m, g; + for (h = 0; h < r; h++) { + v = a.top + h * l, g = h - (r - 1) / 2; + for (p = 0; p < i; p++)d = a.left + p * f, m = p - (i - 1) / 2, s.clone().appendTo("body").wrap("
").css({position: "absolute", visibility: "visible", left: -p * f, top: -h * l}).parent().addClass("ui-effects-explode").css({position: "absolute", overflow: "hidden", width: f, height: l, left: d + (u ? m * f : 0), top: v + (u ? g * l : 0), opacity: u ? 0 : 1}).animate({left: d + (u ? 0 : m * f), top: v + (u ? 0 : g * l), opacity: u ? 1 : 0}, t.duration || 500, t.easing, y) + } + } +})(jQuery); +(function (e, t) { + e.effects.effect.fade = function (t, n) { + var r = e(this), i = e.effects.setMode(r, t.mode || "toggle"); + r.animate({opacity: i}, {queue: !1, duration: t.duration, easing: t.easing, complete: n}) + } +})(jQuery); +(function (e, t) { + e.effects.effect.fold = function (t, n) { + var r = e(this), i = ["position", "top", "bottom", "left", "right", "height", "width"], s = e.effects.setMode(r, t.mode || "hide"), o = s === "show", u = s === "hide", a = t.size || 15, f = /([0-9]+)%/.exec(a), l = !!t.horizFirst, c = o !== l, h = c ? ["width", "height"] : ["height", "width"], p = t.duration / 2, d, v, m = {}, g = {}; + e.effects.save(r, i), r.show(), d = e.effects.createWrapper(r).css({overflow: "hidden"}), v = c ? [d.width(), d.height()] : [d.height(), d.width()], f && (a = parseInt(f[1], 10) / 100 * v[u ? 0 : 1]), o && d.css(l ? {height: 0, width: a} : {height: a, width: 0}), m[h[0]] = o ? v[0] : a, g[h[1]] = o ? v[1] : 0, d.animate(m, p, t.easing).animate(g, p, t.easing, function () { + u && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n() + }) + } +})(jQuery); +(function (e, t) { + e.effects.effect.highlight = function (t, n) { + var r = e(this), i = ["backgroundImage", "backgroundColor", "opacity"], s = e.effects.setMode(r, t.mode || "show"), o = {backgroundColor: r.css("backgroundColor")}; + s === "hide" && (o.opacity = 0), e.effects.save(r, i), r.show().css({backgroundImage: "none", backgroundColor: t.color || "#ffff99"}).animate(o, {queue: !1, duration: t.duration, easing: t.easing, complete: function () { + s === "hide" && r.hide(), e.effects.restore(r, i), n() + }}) + } +})(jQuery); +(function (e, t) { + e.effects.effect.pulsate = function (t, n) { + var r = e(this), i = e.effects.setMode(r, t.mode || "show"), s = i === "show", o = i === "hide", u = s || i === "hide", a = (t.times || 5) * 2 + (u ? 1 : 0), f = t.duration / a, l = 0, c = r.queue(), h = c.length, p; + if (s || !r.is(":visible"))r.css("opacity", 0).show(), l = 1; + for (p = 1; p < a; p++)r.animate({opacity: l}, f, t.easing), l = 1 - l; + r.animate({opacity: l}, f, t.easing), r.queue(function () { + o && r.hide(), n() + }), h > 1 && c.splice.apply(c, [1, 0].concat(c.splice(h, a + 1))), r.dequeue() + } +})(jQuery); +(function (e, t) { + e.effects.effect.puff = function (t, n) { + var r = e(this), i = e.effects.setMode(r, t.mode || "hide"), s = i === "hide", o = parseInt(t.percent, 10) || 150, u = o / 100, a = {height: r.height(), width: r.width()}; + e.extend(t, {effect: "scale", queue: !1, fade: !0, mode: i, complete: n, percent: s ? o : 100, from: s ? a : {height: a.height * u, width: a.width * u}}), r.effect(t) + }, e.effects.effect.scale = function (t, n) { + var r = e(this), i = e.extend(!0, {}, t), s = e.effects.setMode(r, t.mode || "effect"), o = parseInt(t.percent, 10) || (parseInt(t.percent, 10) === 0 ? 0 : s === "hide" ? 0 : 100), u = t.direction || "both", a = t.origin, f = {height: r.height(), width: r.width(), outerHeight: r.outerHeight(), outerWidth: r.outerWidth()}, l = {y: u !== "horizontal" ? o / 100 : 1, x: u !== "vertical" ? o / 100 : 1}; + i.effect = "size", i.queue = !1, i.complete = n, s !== "effect" && (i.origin = a || ["middle", "center"], i.restore = !0), i.from = t.from || (s === "show" ? {height: 0, width: 0} : f), i.to = {height: f.height * l.y, width: f.width * l.x, outerHeight: f.outerHeight * l.y, outerWidth: f.outerWidth * l.x}, i.fade && (s === "show" && (i.from.opacity = 0, i.to.opacity = 1), s === "hide" && (i.from.opacity = 1, i.to.opacity = 0)), r.effect(i) + }, e.effects.effect.size = function (t, n) { + var r, i, s, o = e(this), u = ["position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity"], a = ["position", "top", "bottom", "left", "right", "overflow", "opacity"], f = ["width", "height", "overflow"], l = ["fontSize"], c = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"], h = ["borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight"], p = e.effects.setMode(o, t.mode || "effect"), d = t.restore || p !== "effect", v = t.scale || "both", m = t.origin || ["middle", "center"], g = o.css("position"), y = d ? u : a, b = {height: 0, width: 0}; + p === "show" && o.show(), r = {height: o.height(), width: o.width(), outerHeight: o.outerHeight(), outerWidth: o.outerWidth()}, t.mode === "toggle" && p === "show" ? (o.from = t.to || b, o.to = t.from || r) : (o.from = t.from || (p === "show" ? b : r), o.to = t.to || (p === "hide" ? b : r)), s = {from: {y: o.from.height / r.height, x: o.from.width / r.width}, to: {y: o.to.height / r.height, x: o.to.width / r.width}}; + if (v === "box" || v === "both")s.from.y !== s.to.y && (y = y.concat(c), o.from = e.effects.setTransition(o, c, s.from.y, o.from), o.to = e.effects.setTransition(o, c, s.to.y, o.to)), s.from.x !== s.to.x && (y = y.concat(h), o.from = e.effects.setTransition(o, h, s.from.x, o.from), o.to = e.effects.setTransition(o, h, s.to.x, o.to)); + (v === "content" || v === "both") && s.from.y !== s.to.y && (y = y.concat(l).concat(f), o.from = e.effects.setTransition(o, l, s.from.y, o.from), o.to = e.effects.setTransition(o, l, s.to.y, o.to)), e.effects.save(o, y), o.show(), e.effects.createWrapper(o), o.css("overflow", "hidden").css(o.from), m && (i = e.effects.getBaseline(m, r), o.from.top = (r.outerHeight - o.outerHeight()) * i.y, o.from.left = (r.outerWidth - o.outerWidth()) * i.x, o.to.top = (r.outerHeight - o.to.outerHeight) * i.y, o.to.left = (r.outerWidth - o.to.outerWidth) * i.x), o.css(o.from); + if (v === "content" || v === "both")c = c.concat(["marginTop", "marginBottom"]).concat(l), h = h.concat(["marginLeft", "marginRight"]), f = u.concat(c).concat(h), o.find("*[width]").each(function () { + var n = e(this), r = {height: n.height(), width: n.width()}; + d && e.effects.save(n, f), n.from = {height: r.height * s.from.y, width: r.width * s.from.x}, n.to = {height: r.height * s.to.y, width: r.width * s.to.x}, s.from.y !== s.to.y && (n.from = e.effects.setTransition(n, c, s.from.y, n.from), n.to = e.effects.setTransition(n, c, s.to.y, n.to)), s.from.x !== s.to.x && (n.from = e.effects.setTransition(n, h, s.from.x, n.from), n.to = e.effects.setTransition(n, h, s.to.x, n.to)), n.css(n.from), n.animate(n.to, t.duration, t.easing, function () { + d && e.effects.restore(n, f) + }) + }); + o.animate(o.to, {queue: !1, duration: t.duration, easing: t.easing, complete: function () { + o.to.opacity === 0 && o.css("opacity", o.from.opacity), p === "hide" && o.hide(), e.effects.restore(o, y), d || (g === "static" ? o.css({position: "relative", top: o.to.top, left: o.to.left}) : e.each(["top", "left"], function (e, t) { + o.css(t, function (t, n) { + var r = parseInt(n, 10), i = e ? o.to.left : o.to.top; + return n === "auto" ? i + "px" : r + i + "px" + }) + })), e.effects.removeWrapper(o), n() + }}) + } +})(jQuery); +(function (e, t) { + e.effects.effect.shake = function (t, n) { + var r = e(this), i = ["position", "top", "bottom", "left", "right", "height", "width"], s = e.effects.setMode(r, t.mode || "effect"), o = t.direction || "left", u = t.distance || 20, a = t.times || 3, f = a * 2 + 1, l = Math.round(t.duration / f), c = o === "up" || o === "down" ? "top" : "left", h = o === "up" || o === "left", p = {}, d = {}, v = {}, m, g = r.queue(), y = g.length; + e.effects.save(r, i), r.show(), e.effects.createWrapper(r), p[c] = (h ? "-=" : "+=") + u, d[c] = (h ? "+=" : "-=") + u * 2, v[c] = (h ? "-=" : "+=") + u * 2, r.animate(p, l, t.easing); + for (m = 1; m < a; m++)r.animate(d, l, t.easing).animate(v, l, t.easing); + r.animate(d, l, t.easing).animate(p, l / 2, t.easing).queue(function () { + s === "hide" && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n() + }), y > 1 && g.splice.apply(g, [1, 0].concat(g.splice(y, f + 1))), r.dequeue() + } +})(jQuery); +(function (e, t) { + e.effects.effect.slide = function (t, n) { + var r = e(this), i = ["position", "top", "bottom", "left", "right", "width", "height"], s = e.effects.setMode(r, t.mode || "show"), o = s === "show", u = t.direction || "left", a = u === "up" || u === "down" ? "top" : "left", f = u === "up" || u === "left", l, c = {}; + e.effects.save(r, i), r.show(), l = t.distance || r[a === "top" ? "outerHeight" : "outerWidth"](!0), e.effects.createWrapper(r).css({overflow: "hidden"}), o && r.css(a, f ? isNaN(l) ? "-" + l : -l : l), c[a] = (o ? f ? "+=" : "-=" : f ? "-=" : "+=") + l, r.animate(c, {queue: !1, duration: t.duration, easing: t.easing, complete: function () { + s === "hide" && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n() + }}) + } +})(jQuery); +(function (e, t) { + e.effects.effect.transfer = function (t, n) { + var r = e(this), i = e(t.to), s = i.css("position") === "fixed", o = e("body"), u = s ? o.scrollTop() : 0, a = s ? o.scrollLeft() : 0, f = i.offset(), l = {top: f.top - u, left: f.left - a, height: i.innerHeight(), width: i.innerWidth()}, c = r.offset(), h = e('
').appendTo(document.body).addClass(t.className).css({top: c.top - u, left: c.left - a, height: r.innerHeight(), width: r.innerWidth(), position: s ? "fixed" : "absolute"}).animate(l, t.duration, t.easing, function () { + h.remove(), n() + }) + } +})(jQuery); +(function (e, t) { + var n = !1; + e.widget("ui.menu", {version: "1.9.1", defaultElement: "
    ", delay: 300, options: {icons: {submenu: "ui-icon-carat-1-e"}, menus: "ul", position: {my: "left top", at: "right top"}, role: "menu", blur: null, focus: null, select: null}, _create: function () { + this.activeMenu = this.element, this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons", !!this.element.find(".ui-icon").length).attr({role: this.options.role, tabIndex: 0}).bind("click" + this.eventNamespace, e.proxy(function (e) { + this.options.disabled && e.preventDefault() + }, this)), this.options.disabled && this.element.addClass("ui-state-disabled").attr("aria-disabled", "true"), this._on({"mousedown .ui-menu-item > a": function (e) { + e.preventDefault() + }, "click .ui-state-disabled > a": function (e) { + e.preventDefault() + }, "click .ui-menu-item:has(a)": function (t) { + var r = e(t.target).closest(".ui-menu-item"); + !n && r.not(".ui-state-disabled").length && (n = !0, this.select(t), r.has(".ui-menu").length ? this.expand(t) : this.element.is(":focus") || (this.element.trigger("focus", [!0]), this.active && this.active.parents(".ui-menu").length === 1 && clearTimeout(this.timer))) + }, "mouseenter .ui-menu-item": function (t) { + var n = e(t.currentTarget); + n.siblings().children(".ui-state-active").removeClass("ui-state-active"), this.focus(t, n) + }, mouseleave: "collapseAll", "mouseleave .ui-menu": "collapseAll", focus: function (e, t) { + var n = this.active || this.element.children(".ui-menu-item").eq(0); + t || this.focus(e, n) + }, blur: function (t) { + this._delay(function () { + e.contains(this.element[0], this.document[0].activeElement) || this.collapseAll(t) + }) + }, keydown: "_keydown"}), this.refresh(), this._on(this.document, {click: function (t) { + e(t.target).closest(".ui-menu").length || this.collapseAll(t), n = !1 + }}) + }, _destroy: function () { + this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(), this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function () { + var t = e(this); + t.data("ui-menu-submenu-carat") && t.remove() + }), this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content") + }, _keydown: function (t) { + function a(e) { + return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&") + } + + var n, r, i, s, o, u = !0; + switch (t.keyCode) { + case e.ui.keyCode.PAGE_UP: + this.previousPage(t); + break; + case e.ui.keyCode.PAGE_DOWN: + this.nextPage(t); + break; + case e.ui.keyCode.HOME: + this._move("first", "first", t); + break; + case e.ui.keyCode.END: + this._move("last", "last", t); + break; + case e.ui.keyCode.UP: + this.previous(t); + break; + case e.ui.keyCode.DOWN: + this.next(t); + break; + case e.ui.keyCode.LEFT: + this.collapse(t); + break; + case e.ui.keyCode.RIGHT: + this.active && !this.active.is(".ui-state-disabled") && this.expand(t); + break; + case e.ui.keyCode.ENTER: + case e.ui.keyCode.SPACE: + this._activate(t); + break; + case e.ui.keyCode.ESCAPE: + this.collapse(t); + break; + default: + u = !1, r = this.previousFilter || "", i = String.fromCharCode(t.keyCode), s = !1, clearTimeout(this.filterTimer), i === r ? s = !0 : i = r + i, o = new RegExp("^" + a(i), "i"), n = this.activeMenu.children(".ui-menu-item").filter(function () { + return o.test(e(this).children("a").text()) + }), n = s && n.index(this.active.next()) !== -1 ? this.active.nextAll(".ui-menu-item") : n, n.length || (i = String.fromCharCode(t.keyCode), o = new RegExp("^" + a(i), "i"), n = this.activeMenu.children(".ui-menu-item").filter(function () { + return o.test(e(this).children("a").text()) + })), n.length ? (this.focus(t, n), n.length > 1 ? (this.previousFilter = i, this.filterTimer = this._delay(function () { + delete this.previousFilter + }, 1e3)) : delete this.previousFilter) : delete this.previousFilter + } + u && t.preventDefault() + }, _activate: function (e) { + this.active.is(".ui-state-disabled") || (this.active.children("a[aria-haspopup='true']").length ? this.expand(e) : this.select(e)) + }, refresh: function () { + var t, n = this.options.icons.submenu, r = this.element.find(this.options.menus + ":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role: this.options.role, "aria-hidden": "true", "aria-expanded": "false"}); + t = r.add(this.element), t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role", "presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex: -1, role: this._itemRole()}), t.children(":not(.ui-menu-item)").each(function () { + var t = e(this); + /[^\-—–\s]/.test(t.text()) || t.addClass("ui-widget-content ui-menu-divider") + }), t.children(".ui-state-disabled").attr("aria-disabled", "true"), r.each(function () { + var t = e(this), r = t.prev("a"), i = e("").addClass("ui-menu-icon ui-icon " + n).data("ui-menu-submenu-carat", !0); + r.attr("aria-haspopup", "true").prepend(i), t.attr("aria-labelledby", r.attr("id")) + }), this.active && !e.contains(this.element[0], this.active[0]) && this.blur() + }, _itemRole: function () { + return{menu: "menuitem", listbox: "option"}[this.options.role] + }, focus: function (e, t) { + var n, r; + this.blur(e, e && e.type === "focus"), this._scrollIntoView(t), this.active = t.first(), r = this.active.children("a").addClass("ui-state-focus"), this.options.role && this.element.attr("aria-activedescendant", r.attr("id")), this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"), e && e.type === "keydown" ? this._close() : this.timer = this._delay(function () { + this._close() + }, this.delay), n = t.children(".ui-menu"), n.length && /^mouse/.test(e.type) && this._startOpening(n), this.activeMenu = t.parent(), this._trigger("focus", e, {item: t}) + }, _scrollIntoView: function (t) { + var n, r, i, s, o, u; + this._hasScroll() && (n = parseFloat(e.css(this.activeMenu[0], "borderTopWidth")) || 0, r = parseFloat(e.css(this.activeMenu[0], "paddingTop")) || 0, i = t.offset().top - this.activeMenu.offset().top - n - r, s = this.activeMenu.scrollTop(), o = this.activeMenu.height(), u = t.height(), i < 0 ? this.activeMenu.scrollTop(s + i) : i + u > o && this.activeMenu.scrollTop(s + i - o + u)) + }, blur: function (e, t) { + t || clearTimeout(this.timer); + if (!this.active)return; + this.active.children("a").removeClass("ui-state-focus"), this.active = null, this._trigger("blur", e, {item: this.active}) + }, _startOpening: function (e) { + clearTimeout(this.timer); + if (e.attr("aria-hidden") !== "true")return; + this.timer = this._delay(function () { + this._close(), this._open(e) + }, this.delay) + }, _open: function (t) { + var n = e.extend({of: this.active}, this.options.position); + clearTimeout(this.timer), this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden", "true"), t.show().removeAttr("aria-hidden").attr("aria-expanded", "true").position(n) + }, collapseAll: function (t, n) { + clearTimeout(this.timer), this.timer = this._delay(function () { + var r = n ? this.element : e(t && t.target).closest(this.element.find(".ui-menu")); + r.length || (r = this.element), this._close(r), this.blur(t), this.activeMenu = r + }, this.delay) + }, _close: function (e) { + e || (e = this.active ? this.active.parent() : this.element), e.find(".ui-menu").hide().attr("aria-hidden", "true").attr("aria-expanded", "false").end().find("a.ui-state-active").removeClass("ui-state-active") + }, collapse: function (e) { + var t = this.active && this.active.parent().closest(".ui-menu-item", this.element); + t && t.length && (this._close(), this.focus(e, t)) + }, expand: function (e) { + var t = this.active && this.active.children(".ui-menu ").children(".ui-menu-item").first(); + t && t.length && (this._open(t.parent()), this._delay(function () { + this.focus(e, t) + })) + }, next: function (e) { + this._move("next", "first", e) + }, previous: function (e) { + this._move("prev", "last", e) + }, isFirstItem: function () { + return this.active && !this.active.prevAll(".ui-menu-item").length + }, isLastItem: function () { + return this.active && !this.active.nextAll(".ui-menu-item").length + }, _move: function (e, t, n) { + var r; + this.active && (e === "first" || e === "last" ? r = this.active[e === "first" ? "prevAll" : "nextAll"](".ui-menu-item").eq(-1) : r = this.active[e + "All"](".ui-menu-item").eq(0)); + if (!r || !r.length || !this.active)r = this.activeMenu.children(".ui-menu-item")[t](); + this.focus(n, r) + }, nextPage: function (t) { + var n, r, i; + if (!this.active) { + this.next(t); + return + } + if (this.isLastItem())return; + this._hasScroll() ? (r = this.active.offset().top, i = this.element.height(), this.active.nextAll(".ui-menu-item").each(function () { + return n = e(this), n.offset().top - r - i < 0 + }), this.focus(t, n)) : this.focus(t, this.activeMenu.children(".ui-menu-item")[this.active ? "last" : "first"]()) + }, previousPage: function (t) { + var n, r, i; + if (!this.active) { + this.next(t); + return + } + if (this.isFirstItem())return; + this._hasScroll() ? (r = this.active.offset().top, i = this.element.height(), this.active.prevAll(".ui-menu-item").each(function () { + return n = e(this), n.offset().top - r + i > 0 + }), this.focus(t, n)) : this.focus(t, this.activeMenu.children(".ui-menu-item").first()) + }, _hasScroll: function () { + return this.element.outerHeight() < this.element.prop("scrollHeight") + }, select: function (t) { + this.active = this.active || e(t.target).closest(".ui-menu-item"); + var n = {item: this.active}; + this.active.has(".ui-menu").length || this.collapseAll(t, !0), this._trigger("select", t, n) + }}) +})(jQuery); +(function (e, t) { + e.widget("ui.progressbar", {version: "1.9.1", options: {value: 0, max: 100}, min: 0, _create: function () { + this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role: "progressbar", "aria-valuemin": this.min, "aria-valuemax": this.options.max, "aria-valuenow": this._value()}), this.valueDiv = e("
    ").appendTo(this.element), this.oldValue = this._value(), this._refreshValue() + }, _destroy: function () { + this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"), this.valueDiv.remove() + }, value: function (e) { + return e === t ? this._value() : (this._setOption("value", e), this) + }, _setOption: function (e, t) { + e === "value" && (this.options.value = t, this._refreshValue(), this._value() === this.options.max && this._trigger("complete")), this._super(e, t) + }, _value: function () { + var e = this.options.value; + return typeof e != "number" && (e = 0), Math.min(this.options.max, Math.max(this.min, e)) + }, _percentage: function () { + return 100 * this._value() / this.options.max + }, _refreshValue: function () { + var e = this.value(), t = this._percentage(); + this.oldValue !== e && (this.oldValue = e, this._trigger("change")), this.valueDiv.toggle(e > this.min).toggleClass("ui-corner-right", e === this.options.max).width(t.toFixed(0) + "%"), this.element.attr("aria-valuenow", e) + }}) +})(jQuery); +(function (e, t) { + e.widget("ui.resizable", e.ui.mouse, {version: "1.9.1", widgetEventPrefix: "resize", options: {alsoResize: !1, animate: !1, animateDuration: "slow", animateEasing: "swing", aspectRatio: !1, autoHide: !1, containment: !1, ghost: !1, grid: !1, handles: "e,s,se", helper: !1, maxHeight: null, maxWidth: null, minHeight: 10, minWidth: 10, zIndex: 1e3}, _create: function () { + var t = this, n = this.options; + this.element.addClass("ui-resizable"), e.extend(this, {_aspectRatio: !!n.aspectRatio, aspectRatio: n.aspectRatio, originalElement: this.element, _proportionallyResizeElements: [], _helper: n.helper || n.ghost || n.animate ? n.helper || "ui-resizable-helper" : null}), this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i) && (this.element.wrap(e('
    ').css({position: this.element.css("position"), width: this.element.outerWidth(), height: this.element.outerHeight(), top: this.element.css("top"), left: this.element.css("left")})), this.element = this.element.parent().data("resizable", this.element.data("resizable")), this.elementIsWrapper = !0, this.element.css({marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom")}), this.originalElement.css({marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}), this.originalResizeStyle = this.originalElement.css("resize"), this.originalElement.css("resize", "none"), this._proportionallyResizeElements.push(this.originalElement.css({position: "static", zoom: 1, display: "block"})), this.originalElement.css({margin: this.originalElement.css("margin")}), this._proportionallyResize()), this.handles = n.handles || (e(".ui-resizable-handle", this.element).length ? {n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw"} : "e,s,se"); + if (this.handles.constructor == String) { + this.handles == "all" && (this.handles = "n,e,s,w,se,sw,ne,nw"); + var r = this.handles.split(","); + this.handles = {}; + for (var i = 0; i < r.length; i++) { + var s = e.trim(r[i]), o = "ui-resizable-" + s, u = e('
    '); + u.css({zIndex: n.zIndex}), "se" == s && u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"), this.handles[s] = ".ui-resizable-" + s, this.element.append(u) + } + } + this._renderAxis = function (t) { + t = t || this.element; + for (var n in this.handles) { + this.handles[n].constructor == String && (this.handles[n] = e(this.handles[n], this.element).show()); + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { + var r = e(this.handles[n], this.element), i = 0; + i = /sw|ne|nw|se|n|s/.test(n) ? r.outerHeight() : r.outerWidth(); + var s = ["padding", /ne|nw|n/.test(n) ? "Top" : /se|sw|s/.test(n) ? "Bottom" : /^e$/.test(n) ? "Right" : "Left"].join(""); + t.css(s, i), this._proportionallyResize() + } + if (!e(this.handles[n]).length)continue + } + }, this._renderAxis(this.element), this._handles = e(".ui-resizable-handle", this.element).disableSelection(), this._handles.mouseover(function () { + if (!t.resizing) { + if (this.className)var e = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); + t.axis = e && e[1] ? e[1] : "se" + } + }), n.autoHide && (this._handles.hide(), e(this.element).addClass("ui-resizable-autohide").mouseenter(function () { + if (n.disabled)return; + e(this).removeClass("ui-resizable-autohide"), t._handles.show() + }).mouseleave(function () { + if (n.disabled)return; + t.resizing || (e(this).addClass("ui-resizable-autohide"), t._handles.hide()) + })), this._mouseInit() + }, _destroy: function () { + this._mouseDestroy(); + var t = function (t) { + e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove() + }; + if (this.elementIsWrapper) { + t(this.element); + var n = this.element; + this.originalElement.css({position: n.css("position"), width: n.outerWidth(), height: n.outerHeight(), top: n.css("top"), left: n.css("left")}).insertAfter(n), n.remove() + } + return this.originalElement.css("resize", this.originalResizeStyle), t(this.originalElement), this + }, _mouseCapture: function (t) { + var n = !1; + for (var r in this.handles)e(this.handles[r])[0] == t.target && (n = !0); + return!this.options.disabled && n + }, _mouseStart: function (t) { + var r = this.options, i = this.element.position(), s = this.element; + this.resizing = !0, this.documentScroll = {top: e(document).scrollTop(), left: e(document).scrollLeft()}, (s.is(".ui-draggable") || /absolute/.test(s.css("position"))) && s.css({position: "absolute", top: i.top, left: i.left}), this._renderProxy(); + var o = n(this.helper.css("left")), u = n(this.helper.css("top")); + r.containment && (o += e(r.containment).scrollLeft() || 0, u += e(r.containment).scrollTop() || 0), this.offset = this.helper.offset(), this.position = {left: o, top: u}, this.size = this._helper ? {width: s.outerWidth(), height: s.outerHeight()} : {width: s.width(), height: s.height()}, this.originalSize = this._helper ? {width: s.outerWidth(), height: s.outerHeight()} : {width: s.width(), height: s.height()}, this.originalPosition = {left: o, top: u}, this.sizeDiff = {width: s.outerWidth() - s.width(), height: s.outerHeight() - s.height()}, this.originalMousePosition = {left: t.pageX, top: t.pageY}, this.aspectRatio = typeof r.aspectRatio == "number" ? r.aspectRatio : this.originalSize.width / this.originalSize.height || 1; + var a = e(".ui-resizable-" + this.axis).css("cursor"); + return e("body").css("cursor", a == "auto" ? this.axis + "-resize" : a), s.addClass("ui-resizable-resizing"), this._propagate("start", t), !0 + }, _mouseDrag: function (e) { + var t = this.helper, n = this.options, r = {}, i = this, s = this.originalMousePosition, o = this.axis, u = e.pageX - s.left || 0, a = e.pageY - s.top || 0, f = this._change[o]; + if (!f)return!1; + var l = f.apply(this, [e, u, a]); + this._updateVirtualBoundaries(e.shiftKey); + if (this._aspectRatio || e.shiftKey)l = this._updateRatio(l, e); + return l = this._respectSize(l, e), this._propagate("resize", e), t.css({top: this.position.top + "px", left: this.position.left + "px", width: this.size.width + "px", height: this.size.height + "px"}), !this._helper && this._proportionallyResizeElements.length && this._proportionallyResize(), this._updateCache(l), this._trigger("resize", e, this.ui()), !1 + }, _mouseStop: function (t) { + this.resizing = !1; + var n = this.options, r = this; + if (this._helper) { + var i = this._proportionallyResizeElements, s = i.length && /textarea/i.test(i[0].nodeName), o = s && e.ui.hasScroll(i[0], "left") ? 0 : r.sizeDiff.height, u = s ? 0 : r.sizeDiff.width, a = {width: r.helper.width() - u, height: r.helper.height() - o}, f = parseInt(r.element.css("left"), 10) + (r.position.left - r.originalPosition.left) || null, l = parseInt(r.element.css("top"), 10) + (r.position.top - r.originalPosition.top) || null; + n.animate || this.element.css(e.extend(a, {top: l, left: f})), r.helper.height(r.size.height), r.helper.width(r.size.width), this._helper && !n.animate && this._proportionallyResize() + } + return e("body").css("cursor", "auto"), this.element.removeClass("ui-resizable-resizing"), this._propagate("stop", t), this._helper && this.helper.remove(), !1 + }, _updateVirtualBoundaries: function (e) { + var t = this.options, n, i, s, o, u; + u = {minWidth: r(t.minWidth) ? t.minWidth : 0, maxWidth: r(t.maxWidth) ? t.maxWidth : Infinity, minHeight: r(t.minHeight) ? t.minHeight : 0, maxHeight: r(t.maxHeight) ? t.maxHeight : Infinity}; + if (this._aspectRatio || e)n = u.minHeight * this.aspectRatio, s = u.minWidth / this.aspectRatio, i = u.maxHeight * this.aspectRatio, o = u.maxWidth / this.aspectRatio, n > u.minWidth && (u.minWidth = n), s > u.minHeight && (u.minHeight = s), i < u.maxWidth && (u.maxWidth = i), o < u.maxHeight && (u.maxHeight = o); + this._vBoundaries = u + }, _updateCache: function (e) { + var t = this.options; + this.offset = this.helper.offset(), r(e.left) && (this.position.left = e.left), r(e.top) && (this.position.top = e.top), r(e.height) && (this.size.height = e.height), r(e.width) && (this.size.width = e.width) + }, _updateRatio: function (e, t) { + var n = this.options, i = this.position, s = this.size, o = this.axis; + return r(e.height) ? e.width = e.height * this.aspectRatio : r(e.width) && (e.height = e.width / this.aspectRatio), o == "sw" && (e.left = i.left + (s.width - e.width), e.top = null), o == "nw" && (e.top = i.top + (s.height - e.height), e.left = i.left + (s.width - e.width)), e + }, _respectSize: function (e, t) { + var n = this.helper, i = this._vBoundaries, s = this._aspectRatio || t.shiftKey, o = this.axis, u = r(e.width) && i.maxWidth && i.maxWidth < e.width, a = r(e.height) && i.maxHeight && i.maxHeight < e.height, f = r(e.width) && i.minWidth && i.minWidth > e.width, l = r(e.height) && i.minHeight && i.minHeight > e.height; + f && (e.width = i.minWidth), l && (e.height = i.minHeight), u && (e.width = i.maxWidth), a && (e.height = i.maxHeight); + var c = this.originalPosition.left + this.originalSize.width, h = this.position.top + this.size.height, p = /sw|nw|w/.test(o), d = /nw|ne|n/.test(o); + f && p && (e.left = c - i.minWidth), u && p && (e.left = c - i.maxWidth), l && d && (e.top = h - i.minHeight), a && d && (e.top = h - i.maxHeight); + var v = !e.width && !e.height; + return v && !e.left && e.top ? e.top = null : v && !e.top && e.left && (e.left = null), e + }, _proportionallyResize: function () { + var t = this.options; + if (!this._proportionallyResizeElements.length)return; + var n = this.helper || this.element; + for (var r = 0; r < this._proportionallyResizeElements.length; r++) { + var i = this._proportionallyResizeElements[r]; + if (!this.borderDif) { + var s = [i.css("borderTopWidth"), i.css("borderRightWidth"), i.css("borderBottomWidth"), i.css("borderLeftWidth")], o = [i.css("paddingTop"), i.css("paddingRight"), i.css("paddingBottom"), i.css("paddingLeft")]; + this.borderDif = e.map(s, function (e, t) { + var n = parseInt(e, 10) || 0, r = parseInt(o[t], 10) || 0; + return n + r + }) + } + i.css({height: n.height() - this.borderDif[0] - this.borderDif[2] || 0, width: n.width() - this.borderDif[1] - this.borderDif[3] || 0}) + } + }, _renderProxy: function () { + var t = this.element, n = this.options; + this.elementOffset = t.offset(); + if (this._helper) { + this.helper = this.helper || e('
    '); + var r = e.ui.ie6 ? 1 : 0, i = e.ui.ie6 ? 2 : -1; + this.helper.addClass(this._helper).css({width: this.element.outerWidth() + i, height: this.element.outerHeight() + i, position: "absolute", left: this.elementOffset.left - r + "px", top: this.elementOffset.top - r + "px", zIndex: ++n.zIndex}), this.helper.appendTo("body").disableSelection() + } else this.helper = this.element + }, _change: {e: function (e, t, n) { + return{width: this.originalSize.width + t} + }, w: function (e, t, n) { + var r = this.options, i = this.originalSize, s = this.originalPosition; + return{left: s.left + t, width: i.width - t} + }, n: function (e, t, n) { + var r = this.options, i = this.originalSize, s = this.originalPosition; + return{top: s.top + n, height: i.height - n} + }, s: function (e, t, n) { + return{height: this.originalSize.height + n} + }, se: function (t, n, r) { + return e.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [t, n, r])) + }, sw: function (t, n, r) { + return e.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [t, n, r])) + }, ne: function (t, n, r) { + return e.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [t, n, r])) + }, nw: function (t, n, r) { + return e.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [t, n, r])) + }}, _propagate: function (t, n) { + e.ui.plugin.call(this, t, [n, this.ui()]), t != "resize" && this._trigger(t, n, this.ui()) + }, plugins: {}, ui: function () { + return{originalElement: this.originalElement, element: this.element, helper: this.helper, position: this.position, size: this.size, originalSize: this.originalSize, originalPosition: this.originalPosition} + }}), e.ui.plugin.add("resizable", "alsoResize", {start: function (t, n) { + var r = e(this).data("resizable"), i = r.options, s = function (t) { + e(t).each(function () { + var t = e(this); + t.data("resizable-alsoresize", {width: parseInt(t.width(), 10), height: parseInt(t.height(), 10), left: parseInt(t.css("left"), 10), top: parseInt(t.css("top"), 10)}) + }) + }; + typeof i.alsoResize == "object" && !i.alsoResize.parentNode ? i.alsoResize.length ? (i.alsoResize = i.alsoResize[0], s(i.alsoResize)) : e.each(i.alsoResize, function (e) { + s(e) + }) : s(i.alsoResize) + }, resize: function (t, n) { + var r = e(this).data("resizable"), i = r.options, s = r.originalSize, o = r.originalPosition, u = {height: r.size.height - s.height || 0, width: r.size.width - s.width || 0, top: r.position.top - o.top || 0, left: r.position.left - o.left || 0}, a = function (t, r) { + e(t).each(function () { + var t = e(this), i = e(this).data("resizable-alsoresize"), s = {}, o = r && r.length ? r : t.parents(n.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; + e.each(o, function (e, t) { + var n = (i[t] || 0) + (u[t] || 0); + n && n >= 0 && (s[t] = n || null) + }), t.css(s) + }) + }; + typeof i.alsoResize == "object" && !i.alsoResize.nodeType ? e.each(i.alsoResize, function (e, t) { + a(e, t) + }) : a(i.alsoResize) + }, stop: function (t, n) { + e(this).removeData("resizable-alsoresize") + }}), e.ui.plugin.add("resizable", "animate", {stop: function (t, n) { + var r = e(this).data("resizable"), i = r.options, s = r._proportionallyResizeElements, o = s.length && /textarea/i.test(s[0].nodeName), u = o && e.ui.hasScroll(s[0], "left") ? 0 : r.sizeDiff.height, a = o ? 0 : r.sizeDiff.width, f = {width: r.size.width - a, height: r.size.height - u}, l = parseInt(r.element.css("left"), 10) + (r.position.left - r.originalPosition.left) || null, c = parseInt(r.element.css("top"), 10) + (r.position.top - r.originalPosition.top) || null; + r.element.animate(e.extend(f, c && l ? {top: c, left: l} : {}), {duration: i.animateDuration, easing: i.animateEasing, step: function () { + var n = {width: parseInt(r.element.css("width"), 10), height: parseInt(r.element.css("height"), 10), top: parseInt(r.element.css("top"), 10), left: parseInt(r.element.css("left"), 10)}; + s && s.length && e(s[0]).css({width: n.width, height: n.height}), r._updateCache(n), r._propagate("resize", t) + }}) + }}), e.ui.plugin.add("resizable", "containment", {start: function (t, r) { + var i = e(this).data("resizable"), s = i.options, o = i.element, u = s.containment, a = u instanceof e ? u.get(0) : /parent/.test(u) ? o.parent().get(0) : u; + if (!a)return; + i.containerElement = e(a); + if (/document/.test(u) || u == document)i.containerOffset = {left: 0, top: 0}, i.containerPosition = {left: 0, top: 0}, i.parentData = {element: e(document), left: 0, top: 0, width: e(document).width(), height: e(document).height() || document.body.parentNode.scrollHeight}; else { + var f = e(a), l = []; + e(["Top", "Right", "Left", "Bottom"]).each(function (e, t) { + l[e] = n(f.css("padding" + t)) + }), i.containerOffset = f.offset(), i.containerPosition = f.position(), i.containerSize = {height: f.innerHeight() - l[3], width: f.innerWidth() - l[1]}; + var c = i.containerOffset, h = i.containerSize.height, p = i.containerSize.width, d = e.ui.hasScroll(a, "left") ? a.scrollWidth : p, v = e.ui.hasScroll(a) ? a.scrollHeight : h; + i.parentData = {element: a, left: c.left, top: c.top, width: d, height: v} + } + }, resize: function (t, n) { + var r = e(this).data("resizable"), i = r.options, s = r.containerSize, o = r.containerOffset, u = r.size, a = r.position, f = r._aspectRatio || t.shiftKey, l = {top: 0, left: 0}, c = r.containerElement; + c[0] != document && /static/.test(c.css("position")) && (l = o), a.left < (r._helper ? o.left : 0) && (r.size.width = r.size.width + (r._helper ? r.position.left - o.left : r.position.left - l.left), f && (r.size.height = r.size.width / r.aspectRatio), r.position.left = i.helper ? o.left : 0), a.top < (r._helper ? o.top : 0) && (r.size.height = r.size.height + (r._helper ? r.position.top - o.top : r.position.top), f && (r.size.width = r.size.height * r.aspectRatio), r.position.top = r._helper ? o.top : 0), r.offset.left = r.parentData.left + r.position.left, r.offset.top = r.parentData.top + r.position.top; + var h = Math.abs((r._helper ? r.offset.left - l.left : r.offset.left - l.left) + r.sizeDiff.width), p = Math.abs((r._helper ? r.offset.top - l.top : r.offset.top - o.top) + r.sizeDiff.height), d = r.containerElement.get(0) == r.element.parent().get(0), v = /relative|absolute/.test(r.containerElement.css("position")); + d && v && (h -= r.parentData.left), h + r.size.width >= r.parentData.width && (r.size.width = r.parentData.width - h, f && (r.size.height = r.size.width / r.aspectRatio)), p + r.size.height >= r.parentData.height && (r.size.height = r.parentData.height - p, f && (r.size.width = r.size.height * r.aspectRatio)) + }, stop: function (t, n) { + var r = e(this).data("resizable"), i = r.options, s = r.position, o = r.containerOffset, u = r.containerPosition, a = r.containerElement, f = e(r.helper), l = f.offset(), c = f.outerWidth() - r.sizeDiff.width, h = f.outerHeight() - r.sizeDiff.height; + r._helper && !i.animate && /relative/.test(a.css("position")) && e(this).css({left: l.left - u.left - o.left, width: c, height: h}), r._helper && !i.animate && /static/.test(a.css("position")) && e(this).css({left: l.left - u.left - o.left, width: c, height: h}) + }}), e.ui.plugin.add("resizable", "ghost", {start: function (t, n) { + var r = e(this).data("resizable"), i = r.options, s = r.size; + r.ghost = r.originalElement.clone(), r.ghost.css({opacity: .25, display: "block", position: "relative", height: s.height, width: s.width, margin: 0, left: 0, top: 0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost == "string" ? i.ghost : ""), r.ghost.appendTo(r.helper) + }, resize: function (t, n) { + var r = e(this).data("resizable"), i = r.options; + r.ghost && r.ghost.css({position: "relative", height: r.size.height, width: r.size.width}) + }, stop: function (t, n) { + var r = e(this).data("resizable"), i = r.options; + r.ghost && r.helper && r.helper.get(0).removeChild(r.ghost.get(0)) + }}), e.ui.plugin.add("resizable", "grid", {resize: function (t, n) { + var r = e(this).data("resizable"), i = r.options, s = r.size, o = r.originalSize, u = r.originalPosition, a = r.axis, f = i._aspectRatio || t.shiftKey; + i.grid = typeof i.grid == "number" ? [i.grid, i.grid] : i.grid; + var l = Math.round((s.width - o.width) / (i.grid[0] || 1)) * (i.grid[0] || 1), c = Math.round((s.height - o.height) / (i.grid[1] || 1)) * (i.grid[1] || 1); + /^(se|s|e)$/.test(a) ? (r.size.width = o.width + l, r.size.height = o.height + c) : /^(ne)$/.test(a) ? (r.size.width = o.width + l, r.size.height = o.height + c, r.position.top = u.top - c) : /^(sw)$/.test(a) ? (r.size.width = o.width + l, r.size.height = o.height + c, r.position.left = u.left - l) : (r.size.width = o.width + l, r.size.height = o.height + c, r.position.top = u.top - c, r.position.left = u.left - l) + }}); + var n = function (e) { + return parseInt(e, 10) || 0 + }, r = function (e) { + return!isNaN(parseInt(e, 10)) + } +})(jQuery); +(function (e, t) { + e.widget("ui.selectable", e.ui.mouse, {version: "1.9.1", options: {appendTo: "body", autoRefresh: !0, distance: 0, filter: "*", tolerance: "touch"}, _create: function () { + var t = this; + this.element.addClass("ui-selectable"), this.dragged = !1; + var n; + this.refresh = function () { + n = e(t.options.filter, t.element[0]), n.addClass("ui-selectee"), n.each(function () { + var t = e(this), n = t.offset(); + e.data(this, "selectable-item", {element: this, $element: t, left: n.left, top: n.top, right: n.left + t.outerWidth(), bottom: n.top + t.outerHeight(), startselected: !1, selected: t.hasClass("ui-selected"), selecting: t.hasClass("ui-selecting"), unselecting: t.hasClass("ui-unselecting")}) + }) + }, this.refresh(), this.selectees = n.addClass("ui-selectee"), this._mouseInit(), this.helper = e("
    ") + }, _destroy: function () { + this.selectees.removeClass("ui-selectee").removeData("selectable-item"), this.element.removeClass("ui-selectable ui-selectable-disabled"), this._mouseDestroy() + }, _mouseStart: function (t) { + var n = this; + this.opos = [t.pageX, t.pageY]; + if (this.options.disabled)return; + var r = this.options; + this.selectees = e(r.filter, this.element[0]), this._trigger("start", t), e(r.appendTo).append(this.helper), this.helper.css({left: t.clientX, top: t.clientY, width: 0, height: 0}), r.autoRefresh && this.refresh(), this.selectees.filter(".ui-selected").each(function () { + var r = e.data(this, "selectable-item"); + r.startselected = !0, !t.metaKey && !t.ctrlKey && (r.$element.removeClass("ui-selected"), r.selected = !1, r.$element.addClass("ui-unselecting"), r.unselecting = !0, n._trigger("unselecting", t, {unselecting: r.element})) + }), e(t.target).parents().andSelf().each(function () { + var r = e.data(this, "selectable-item"); + if (r) { + var i = !t.metaKey && !t.ctrlKey || !r.$element.hasClass("ui-selected"); + return r.$element.removeClass(i ? "ui-unselecting" : "ui-selected").addClass(i ? "ui-selecting" : "ui-unselecting"), r.unselecting = !i, r.selecting = i, r.selected = i, i ? n._trigger("selecting", t, {selecting: r.element}) : n._trigger("unselecting", t, {unselecting: r.element}), !1 + } + }) + }, _mouseDrag: function (t) { + var n = this; + this.dragged = !0; + if (this.options.disabled)return; + var r = this.options, i = this.opos[0], s = this.opos[1], o = t.pageX, u = t.pageY; + if (i > o) { + var a = o; + o = i, i = a + } + if (s > u) { + var a = u; + u = s, s = a + } + return this.helper.css({left: i, top: s, width: o - i, height: u - s}), this.selectees.each(function () { + var a = e.data(this, "selectable-item"); + if (!a || a.element == n.element[0])return; + var f = !1; + r.tolerance == "touch" ? f = !(a.left > o || a.right < i || a.top > u || a.bottom < s) : r.tolerance == "fit" && (f = a.left > i && a.right < o && a.top > s && a.bottom < u), f ? (a.selected && (a.$element.removeClass("ui-selected"), a.selected = !1), a.unselecting && (a.$element.removeClass("ui-unselecting"), a.unselecting = !1), a.selecting || (a.$element.addClass("ui-selecting"), a.selecting = !0, n._trigger("selecting", t, {selecting: a.element}))) : (a.selecting && ((t.metaKey || t.ctrlKey) && a.startselected ? (a.$element.removeClass("ui-selecting"), a.selecting = !1, a.$element.addClass("ui-selected"), a.selected = !0) : (a.$element.removeClass("ui-selecting"), a.selecting = !1, a.startselected && (a.$element.addClass("ui-unselecting"), a.unselecting = !0), n._trigger("unselecting", t, {unselecting: a.element}))), a.selected && !t.metaKey && !t.ctrlKey && !a.startselected && (a.$element.removeClass("ui-selected"), a.selected = !1, a.$element.addClass("ui-unselecting"), a.unselecting = !0, n._trigger("unselecting", t, {unselecting: a.element}))) + }), !1 + }, _mouseStop: function (t) { + var n = this; + this.dragged = !1; + var r = this.options; + return e(".ui-unselecting", this.element[0]).each(function () { + var r = e.data(this, "selectable-item"); + r.$element.removeClass("ui-unselecting"), r.unselecting = !1, r.startselected = !1, n._trigger("unselected", t, {unselected: r.element}) + }), e(".ui-selecting", this.element[0]).each(function () { + var r = e.data(this, "selectable-item"); + r.$element.removeClass("ui-selecting").addClass("ui-selected"), r.selecting = !1, r.selected = !0, r.startselected = !0, n._trigger("selected", t, {selected: r.element}) + }), this._trigger("stop", t), this.helper.remove(), !1 + }}) +})(jQuery); +(function (e, t) { + var n = 5; + e.widget("ui.slider", e.ui.mouse, {version: "1.9.1", widgetEventPrefix: "slide", options: {animate: !1, distance: 0, max: 100, min: 0, orientation: "horizontal", range: !1, step: 1, value: 0, values: null}, _create: function () { + var t, r, i = this.options, s = this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"), o = "", u = []; + this._keySliding = !1, this._mouseSliding = !1, this._animateOff = !0, this._handleIndex = null, this._detectOrientation(), this._mouseInit(), this.element.addClass("ui-slider ui-slider-" + this.orientation + " ui-widget" + " ui-widget-content" + " ui-corner-all" + (i.disabled ? " ui-slider-disabled ui-disabled" : "")), this.range = e([]), i.range && (i.range === !0 && (i.values || (i.values = [this._valueMin(), this._valueMin()]), i.values.length && i.values.length !== 2 && (i.values = [i.values[0], i.values[0]])), this.range = e("
    ").appendTo(this.element).addClass("ui-slider-range ui-widget-header" + (i.range === "min" || i.range === "max" ? " ui-slider-range-" + i.range : ""))), r = i.values && i.values.length || 1; + for (t = s.length; t < r; t++)u.push(o); + this.handles = s.add(e(u.join("")).appendTo(this.element)), this.handle = this.handles.eq(0), this.handles.add(this.range).filter("a").click(function (e) { + e.preventDefault() + }).mouseenter(function () { + i.disabled || e(this).addClass("ui-state-hover") + }).mouseleave(function () { + e(this).removeClass("ui-state-hover") + }).focus(function () { + i.disabled ? e(this).blur() : (e(".ui-slider .ui-state-focus").removeClass("ui-state-focus"), e(this).addClass("ui-state-focus")) + }).blur(function () { + e(this).removeClass("ui-state-focus") + }), this.handles.each(function (t) { + e(this).data("ui-slider-handle-index", t) + }), this._on(this.handles, {keydown: function (t) { + var r, i, s, o, u = e(t.target).data("ui-slider-handle-index"); + switch (t.keyCode) { + case e.ui.keyCode.HOME: + case e.ui.keyCode.END: + case e.ui.keyCode.PAGE_UP: + case e.ui.keyCode.PAGE_DOWN: + case e.ui.keyCode.UP: + case e.ui.keyCode.RIGHT: + case e.ui.keyCode.DOWN: + case e.ui.keyCode.LEFT: + t.preventDefault(); + if (!this._keySliding) { + this._keySliding = !0, e(t.target).addClass("ui-state-active"), r = this._start(t, u); + if (r === !1)return + } + } + o = this.options.step, this.options.values && this.options.values.length ? i = s = this.values(u) : i = s = this.value(); + switch (t.keyCode) { + case e.ui.keyCode.HOME: + s = this._valueMin(); + break; + case e.ui.keyCode.END: + s = this._valueMax(); + break; + case e.ui.keyCode.PAGE_UP: + s = this._trimAlignValue(i + (this._valueMax() - this._valueMin()) / n); + break; + case e.ui.keyCode.PAGE_DOWN: + s = this._trimAlignValue(i - (this._valueMax() - this._valueMin()) / n); + break; + case e.ui.keyCode.UP: + case e.ui.keyCode.RIGHT: + if (i === this._valueMax())return; + s = this._trimAlignValue(i + o); + break; + case e.ui.keyCode.DOWN: + case e.ui.keyCode.LEFT: + if (i === this._valueMin())return; + s = this._trimAlignValue(i - o) + } + this._slide(t, u, s) + }, keyup: function (t) { + var n = e(t.target).data("ui-slider-handle-index"); + this._keySliding && (this._keySliding = !1, this._stop(t, n), this._change(t, n), e(t.target).removeClass("ui-state-active")) + }}), this._refreshValue(), this._animateOff = !1 + }, _destroy: function () { + this.handles.remove(), this.range.remove(), this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all"), this._mouseDestroy() + }, _mouseCapture: function (t) { + var n, r, i, s, o, u, a, f, l = this, c = this.options; + return c.disabled ? !1 : (this.elementSize = {width: this.element.outerWidth(), height: this.element.outerHeight()}, this.elementOffset = this.element.offset(), n = {x: t.pageX, y: t.pageY}, r = this._normValueFromMouse(n), i = this._valueMax() - this._valueMin() + 1, this.handles.each(function (t) { + var n = Math.abs(r - l.values(t)); + i > n && (i = n, s = e(this), o = t) + }), c.range === !0 && this.values(1) === c.min && (o += 1, s = e(this.handles[o])), u = this._start(t, o), u === !1 ? !1 : (this._mouseSliding = !0, this._handleIndex = o, s.addClass("ui-state-active").focus(), a = s.offset(), f = !e(t.target).parents().andSelf().is(".ui-slider-handle"), this._clickOffset = f ? {left: 0, top: 0} : {left: t.pageX - a.left - s.width() / 2, top: t.pageY - a.top - s.height() / 2 - (parseInt(s.css("borderTopWidth"), 10) || 0) - (parseInt(s.css("borderBottomWidth"), 10) || 0) + (parseInt(s.css("marginTop"), 10) || 0)}, this.handles.hasClass("ui-state-hover") || this._slide(t, o, r), this._animateOff = !0, !0)) + }, _mouseStart: function () { + return!0 + }, _mouseDrag: function (e) { + var t = {x: e.pageX, y: e.pageY}, n = this._normValueFromMouse(t); + return this._slide(e, this._handleIndex, n), !1 + }, _mouseStop: function (e) { + return this.handles.removeClass("ui-state-active"), this._mouseSliding = !1, this._stop(e, this._handleIndex), this._change(e, this._handleIndex), this._handleIndex = null, this._clickOffset = null, this._animateOff = !1, !1 + }, _detectOrientation: function () { + this.orientation = this.options.orientation === "vertical" ? "vertical" : "horizontal" + }, _normValueFromMouse: function (e) { + var t, n, r, i, s; + return this.orientation === "horizontal" ? (t = this.elementSize.width, n = e.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0)) : (t = this.elementSize.height, n = e.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0)), r = n / t, r > 1 && (r = 1), r < 0 && (r = 0), this.orientation === "vertical" && (r = 1 - r), i = this._valueMax() - this._valueMin(), s = this._valueMin() + r * i, this._trimAlignValue(s) + }, _start: function (e, t) { + var n = {handle: this.handles[t], value: this.value()}; + return this.options.values && this.options.values.length && (n.value = this.values(t), n.values = this.values()), this._trigger("start", e, n) + }, _slide: function (e, t, n) { + var r, i, s; + this.options.values && this.options.values.length ? (r = this.values(t ? 0 : 1), this.options.values.length === 2 && this.options.range === !0 && (t === 0 && n > r || t === 1 && n < r) && (n = r), n !== this.values(t) && (i = this.values(), i[t] = n, s = this._trigger("slide", e, {handle: this.handles[t], value: n, values: i}), r = this.values(t ? 0 : 1), s !== !1 && this.values(t, n, !0))) : n !== this.value() && (s = this._trigger("slide", e, {handle: this.handles[t], value: n}), s !== !1 && this.value(n)) + }, _stop: function (e, t) { + var n = {handle: this.handles[t], value: this.value()}; + this.options.values && this.options.values.length && (n.value = this.values(t), n.values = this.values()), this._trigger("stop", e, n) + }, _change: function (e, t) { + if (!this._keySliding && !this._mouseSliding) { + var n = {handle: this.handles[t], value: this.value()}; + this.options.values && this.options.values.length && (n.value = this.values(t), n.values = this.values()), this._trigger("change", e, n) + } + }, value: function (e) { + if (arguments.length) { + this.options.value = this._trimAlignValue(e), this._refreshValue(), this._change(null, 0); + return + } + return this._value() + }, values: function (t, n) { + var r, i, s; + if (arguments.length > 1) { + this.options.values[t] = this._trimAlignValue(n), this._refreshValue(), this._change(null, t); + return + } + if (!arguments.length)return this._values(); + if (!e.isArray(arguments[0]))return this.options.values && this.options.values.length ? this._values(t) : this.value(); + r = this.options.values, i = arguments[0]; + for (s = 0; s < r.length; s += 1)r[s] = this._trimAlignValue(i[s]), this._change(null, s); + this._refreshValue() + }, _setOption: function (t, n) { + var r, i = 0; + e.isArray(this.options.values) && (i = this.options.values.length), e.Widget.prototype._setOption.apply(this, arguments); + switch (t) { + case"disabled": + n ? (this.handles.filter(".ui-state-focus").blur(), this.handles.removeClass("ui-state-hover"), this.handles.prop("disabled", !0), this.element.addClass("ui-disabled")) : (this.handles.prop("disabled", !1), this.element.removeClass("ui-disabled")); + break; + case"orientation": + this._detectOrientation(), this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-" + this.orientation), this._refreshValue(); + break; + case"value": + this._animateOff = !0, this._refreshValue(), this._change(null, 0), this._animateOff = !1; + break; + case"values": + this._animateOff = !0, this._refreshValue(); + for (r = 0; r < i; r += 1)this._change(null, r); + this._animateOff = !1; + break; + case"min": + case"max": + this._animateOff = !0, this._refreshValue(), this._animateOff = !1 + } + }, _value: function () { + var e = this.options.value; + return e = this._trimAlignValue(e), e + }, _values: function (e) { + var t, n, r; + if (arguments.length)return t = this.options.values[e], t = this._trimAlignValue(t), t; + n = this.options.values.slice(); + for (r = 0; r < n.length; r += 1)n[r] = this._trimAlignValue(n[r]); + return n + }, _trimAlignValue: function (e) { + if (e <= this._valueMin())return this._valueMin(); + if (e >= this._valueMax())return this._valueMax(); + var t = this.options.step > 0 ? this.options.step : 1, n = (e - this._valueMin()) % t, r = e - n; + return Math.abs(n) * 2 >= t && (r += n > 0 ? t : -t), parseFloat(r.toFixed(5)) + }, _valueMin: function () { + return this.options.min + }, _valueMax: function () { + return this.options.max + }, _refreshValue: function () { + var t, n, r, i, s, o = this.options.range, u = this.options, a = this, f = this._animateOff ? !1 : u.animate, l = {}; + this.options.values && this.options.values.length ? this.handles.each(function (r) { + n = (a.values(r) - a._valueMin()) / (a._valueMax() - a._valueMin()) * 100, l[a.orientation === "horizontal" ? "left" : "bottom"] = n + "%", e(this).stop(1, 1)[f ? "animate" : "css"](l, u.animate), a.options.range === !0 && (a.orientation === "horizontal" ? (r === 0 && a.range.stop(1, 1)[f ? "animate" : "css"]({left: n + "%"}, u.animate), r === 1 && a.range[f ? "animate" : "css"]({width: n - t + "%"}, {queue: !1, duration: u.animate})) : (r === 0 && a.range.stop(1, 1)[f ? "animate" : "css"]({bottom: n + "%"}, u.animate), r === 1 && a.range[f ? "animate" : "css"]({height: n - t + "%"}, {queue: !1, duration: u.animate}))), t = n + }) : (r = this.value(), i = this._valueMin(), s = this._valueMax(), n = s !== i ? (r - i) / (s - i) * 100 : 0, l[this.orientation === "horizontal" ? "left" : "bottom"] = n + "%", this.handle.stop(1, 1)[f ? "animate" : "css"](l, u.animate), o === "min" && this.orientation === "horizontal" && this.range.stop(1, 1)[f ? "animate" : "css"]({width: n + "%"}, u.animate), o === "max" && this.orientation === "horizontal" && this.range[f ? "animate" : "css"]({width: 100 - n + "%"}, {queue: !1, duration: u.animate}), o === "min" && this.orientation === "vertical" && this.range.stop(1, 1)[f ? "animate" : "css"]({height: n + "%"}, u.animate), o === "max" && this.orientation === "vertical" && this.range[f ? "animate" : "css"]({height: 100 - n + "%"}, {queue: !1, duration: u.animate})) + }}) +})(jQuery); +(function (e, t) { + e.widget("ui.sortable", e.ui.mouse, {version: "1.9.1", widgetEventPrefix: "sort", ready: !1, options: {appendTo: "parent", axis: !1, connectWith: !1, containment: !1, cursor: "auto", cursorAt: !1, dropOnEmpty: !0, forcePlaceholderSize: !1, forceHelperSize: !1, grid: !1, handle: !1, helper: "original", items: "> *", opacity: !1, placeholder: !1, revert: !1, scroll: !0, scrollSensitivity: 20, scrollSpeed: 20, scope: "default", tolerance: "intersect", zIndex: 1e3}, _create: function () { + var e = this.options; + this.containerCache = {}, this.element.addClass("ui-sortable"), this.refresh(), this.floating = this.items.length ? e.axis === "x" || /left|right/.test(this.items[0].item.css("float")) || /inline|table-cell/.test(this.items[0].item.css("display")) : !1, this.offset = this.element.offset(), this._mouseInit(), this.ready = !0 + }, _destroy: function () { + this.element.removeClass("ui-sortable ui-sortable-disabled"), this._mouseDestroy(); + for (var e = this.items.length - 1; e >= 0; e--)this.items[e].item.removeData(this.widgetName + "-item"); + return this + }, _setOption: function (t, n) { + t === "disabled" ? (this.options[t] = n, this.widget().toggleClass("ui-sortable-disabled", !!n)) : e.Widget.prototype._setOption.apply(this, arguments) + }, _mouseCapture: function (t, n) { + var r = this; + if (this.reverting)return!1; + if (this.options.disabled || this.options.type == "static")return!1; + this._refreshItems(t); + var i = null, s = e(t.target).parents().each(function () { + if (e.data(this, r.widgetName + "-item") == r)return i = e(this), !1 + }); + e.data(t.target, r.widgetName + "-item") == r && (i = e(t.target)); + if (!i)return!1; + if (this.options.handle && !n) { + var o = !1; + e(this.options.handle, i).find("*").andSelf().each(function () { + this == t.target && (o = !0) + }); + if (!o)return!1 + } + return this.currentItem = i, this._removeCurrentsFromItems(), !0 + }, _mouseStart: function (t, n, r) { + var i = this.options; + this.currentContainer = this, this.refreshPositions(), this.helper = this._createHelper(t), this._cacheHelperProportions(), this._cacheMargins(), this.scrollParent = this.helper.scrollParent(), this.offset = this.currentItem.offset(), this.offset = {top: this.offset.top - this.margins.top, left: this.offset.left - this.margins.left}, e.extend(this.offset, {click: {left: t.pageX - this.offset.left, top: t.pageY - this.offset.top}, parent: this._getParentOffset(), relative: this._getRelativeOffset()}), this.helper.css("position", "absolute"), this.cssPosition = this.helper.css("position"), this.originalPosition = this._generatePosition(t), this.originalPageX = t.pageX, this.originalPageY = t.pageY, i.cursorAt && this._adjustOffsetFromHelper(i.cursorAt), this.domPosition = {prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0]}, this.helper[0] != this.currentItem[0] && this.currentItem.hide(), this._createPlaceholder(), i.containment && this._setContainment(), i.cursor && (e("body").css("cursor") && (this._storedCursor = e("body").css("cursor")), e("body").css("cursor", i.cursor)), i.opacity && (this.helper.css("opacity") && (this._storedOpacity = this.helper.css("opacity")), this.helper.css("opacity", i.opacity)), i.zIndex && (this.helper.css("zIndex") && (this._storedZIndex = this.helper.css("zIndex")), this.helper.css("zIndex", i.zIndex)), this.scrollParent[0] != document && this.scrollParent[0].tagName != "HTML" && (this.overflowOffset = this.scrollParent.offset()), this._trigger("start", t, this._uiHash()), this._preserveHelperProportions || this._cacheHelperProportions(); + if (!r)for (var s = this.containers.length - 1; s >= 0; s--)this.containers[s]._trigger("activate", t, this._uiHash(this)); + return e.ui.ddmanager && (e.ui.ddmanager.current = this), e.ui.ddmanager && !i.dropBehaviour && e.ui.ddmanager.prepareOffsets(this, t), this.dragging = !0, this.helper.addClass("ui-sortable-helper"), this._mouseDrag(t), !0 + }, _mouseDrag: function (t) { + this.position = this._generatePosition(t), this.positionAbs = this._convertPositionTo("absolute"), this.lastPositionAbs || (this.lastPositionAbs = this.positionAbs); + if (this.options.scroll) { + var n = this.options, r = !1; + this.scrollParent[0] != document && this.scrollParent[0].tagName != "HTML" ? (this.overflowOffset.top + this.scrollParent[0].offsetHeight - t.pageY < n.scrollSensitivity ? this.scrollParent[0].scrollTop = r = this.scrollParent[0].scrollTop + n.scrollSpeed : t.pageY - this.overflowOffset.top < n.scrollSensitivity && (this.scrollParent[0].scrollTop = r = this.scrollParent[0].scrollTop - n.scrollSpeed), this.overflowOffset.left + this.scrollParent[0].offsetWidth - t.pageX < n.scrollSensitivity ? this.scrollParent[0].scrollLeft = r = this.scrollParent[0].scrollLeft + n.scrollSpeed : t.pageX - this.overflowOffset.left < n.scrollSensitivity && (this.scrollParent[0].scrollLeft = r = this.scrollParent[0].scrollLeft - n.scrollSpeed)) : (t.pageY - e(document).scrollTop() < n.scrollSensitivity ? r = e(document).scrollTop(e(document).scrollTop() - n.scrollSpeed) : e(window).height() - (t.pageY - e(document).scrollTop()) < n.scrollSensitivity && (r = e(document).scrollTop(e(document).scrollTop() + n.scrollSpeed)), t.pageX - e(document).scrollLeft() < n.scrollSensitivity ? r = e(document).scrollLeft(e(document).scrollLeft() - n.scrollSpeed) : e(window).width() - (t.pageX - e(document).scrollLeft()) < n.scrollSensitivity && (r = e(document).scrollLeft(e(document).scrollLeft() + n.scrollSpeed))), r !== !1 && e.ui.ddmanager && !n.dropBehaviour && e.ui.ddmanager.prepareOffsets(this, t) + } + this.positionAbs = this._convertPositionTo("absolute"); + if (!this.options.axis || this.options.axis != "y")this.helper[0].style.left = this.position.left + "px"; + if (!this.options.axis || this.options.axis != "x")this.helper[0].style.top = this.position.top + "px"; + for (var i = this.items.length - 1; i >= 0; i--) { + var s = this.items[i], o = s.item[0], u = this._intersectsWithPointer(s); + if (!u)continue; + if (s.instance !== this.currentContainer)continue; + if (o != this.currentItem[0] && this.placeholder[u == 1 ? "next" : "prev"]()[0] != o && !e.contains(this.placeholder[0], o) && (this.options.type == "semi-dynamic" ? !e.contains(this.element[0], o) : !0)) { + this.direction = u == 1 ? "down" : "up"; + if (this.options.tolerance != "pointer" && !this._intersectsWithSides(s))break; + this._rearrange(t, s), this._trigger("change", t, this._uiHash()); + break + } + } + return this._contactContainers(t), e.ui.ddmanager && e.ui.ddmanager.drag(this, t), this._trigger("sort", t, this._uiHash()), this.lastPositionAbs = this.positionAbs, !1 + }, _mouseStop: function (t, n) { + if (!t)return; + e.ui.ddmanager && !this.options.dropBehaviour && e.ui.ddmanager.drop(this, t); + if (this.options.revert) { + var r = this, i = this.placeholder.offset(); + this.reverting = !0, e(this.helper).animate({left: i.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), top: i.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)}, parseInt(this.options.revert, 10) || 500, function () { + r._clear(t) + }) + } else this._clear(t, n); + return!1 + }, cancel: function () { + if (this.dragging) { + this._mouseUp({target: null}), this.options.helper == "original" ? this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper") : this.currentItem.show(); + for (var t = this.containers.length - 1; t >= 0; t--)this.containers[t]._trigger("deactivate", null, this._uiHash(this)), this.containers[t].containerCache.over && (this.containers[t]._trigger("out", null, this._uiHash(this)), this.containers[t].containerCache.over = 0) + } + return this.placeholder && (this.placeholder[0].parentNode && this.placeholder[0].parentNode.removeChild(this.placeholder[0]), this.options.helper != "original" && this.helper && this.helper[0].parentNode && this.helper.remove(), e.extend(this, {helper: null, dragging: !1, reverting: !1, _noFinalSort: null}), this.domPosition.prev ? e(this.domPosition.prev).after(this.currentItem) : e(this.domPosition.parent).prepend(this.currentItem)), this + }, serialize: function (t) { + var n = this._getItemsAsjQuery(t && t.connected), r = []; + return t = t || {}, e(n).each(function () { + var n = (e(t.item || this).attr(t.attribute || "id") || "").match(t.expression || /(.+)[-=_](.+)/); + n && r.push((t.key || n[1] + "[]") + "=" + (t.key && t.expression ? n[1] : n[2])) + }), !r.length && t.key && r.push(t.key + "="), r.join("&") + }, toArray: function (t) { + var n = this._getItemsAsjQuery(t && t.connected), r = []; + return t = t || {}, n.each(function () { + r.push(e(t.item || this).attr(t.attribute || "id") || "") + }), r + }, _intersectsWith: function (e) { + var t = this.positionAbs.left, n = t + this.helperProportions.width, r = this.positionAbs.top, i = r + this.helperProportions.height, s = e.left, o = s + e.width, u = e.top, a = u + e.height, f = this.offset.click.top, l = this.offset.click.left, c = r + f > u && r + f < a && t + l > s && t + l < o; + return this.options.tolerance == "pointer" || this.options.forcePointerForContainers || this.options.tolerance != "pointer" && this.helperProportions[this.floating ? "width" : "height"] > e[this.floating ? "width" : "height"] ? c : s < t + this.helperProportions.width / 2 && n - this.helperProportions.width / 2 < o && u < r + this.helperProportions.height / 2 && i - this.helperProportions.height / 2 < a + }, _intersectsWithPointer: function (t) { + var n = this.options.axis === "x" || e.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, t.top, t.height), r = this.options.axis === "y" || e.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, t.left, t.width), i = n && r, s = this._getDragVerticalDirection(), o = this._getDragHorizontalDirection(); + return i ? this.floating ? o && o == "right" || s == "down" ? 2 : 1 : s && (s == "down" ? 2 : 1) : !1 + }, _intersectsWithSides: function (t) { + var n = e.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, t.top + t.height / 2, t.height), r = e.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, t.left + t.width / 2, t.width), i = this._getDragVerticalDirection(), s = this._getDragHorizontalDirection(); + return this.floating && s ? s == "right" && r || s == "left" && !r : i && (i == "down" && n || i == "up" && !n) + }, _getDragVerticalDirection: function () { + var e = this.positionAbs.top - this.lastPositionAbs.top; + return e != 0 && (e > 0 ? "down" : "up") + }, _getDragHorizontalDirection: function () { + var e = this.positionAbs.left - this.lastPositionAbs.left; + return e != 0 && (e > 0 ? "right" : "left") + }, refresh: function (e) { + return this._refreshItems(e), this.refreshPositions(), this + }, _connectWith: function () { + var e = this.options; + return e.connectWith.constructor == String ? [e.connectWith] : e.connectWith + }, _getItemsAsjQuery: function (t) { + var n = [], r = [], i = this._connectWith(); + if (i && t)for (var s = i.length - 1; s >= 0; s--) { + var o = e(i[s]); + for (var u = o.length - 1; u >= 0; u--) { + var a = e.data(o[u], this.widgetName); + a && a != this && !a.options.disabled && r.push([e.isFunction(a.options.items) ? a.options.items.call(a.element) : e(a.options.items, a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), a]) + } + } + r.push([e.isFunction(this.options.items) ? this.options.items.call(this.element, null, {options: this.options, item: this.currentItem}) : e(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]); + for (var s = r.length - 1; s >= 0; s--)r[s][0].each(function () { + n.push(this) + }); + return e(n) + }, _removeCurrentsFromItems: function () { + var t = this.currentItem.find(":data(" + this.widgetName + "-item)"); + this.items = e.grep(this.items, function (e) { + for (var n = 0; n < t.length; n++)if (t[n] == e.item[0])return!1; + return!0 + }) + }, _refreshItems: function (t) { + this.items = [], this.containers = [this]; + var n = this.items, r = [ + [e.isFunction(this.options.items) ? this.options.items.call(this.element[0], t, {item: this.currentItem}) : e(this.options.items, this.element), this] + ], i = this._connectWith(); + if (i && this.ready)for (var s = i.length - 1; s >= 0; s--) { + var o = e(i[s]); + for (var u = o.length - 1; u >= 0; u--) { + var a = e.data(o[u], this.widgetName); + a && a != this && !a.options.disabled && (r.push([e.isFunction(a.options.items) ? a.options.items.call(a.element[0], t, {item: this.currentItem}) : e(a.options.items, a.element), a]), this.containers.push(a)) + } + } + for (var s = r.length - 1; s >= 0; s--) { + var f = r[s][1], l = r[s][0]; + for (var u = 0, c = l.length; u < c; u++) { + var h = e(l[u]); + h.data(this.widgetName + "-item", f), n.push({item: h, instance: f, width: 0, height: 0, left: 0, top: 0}) + } + } + }, refreshPositions: function (t) { + this.offsetParent && this.helper && (this.offset.parent = this._getParentOffset()); + for (var n = this.items.length - 1; n >= 0; n--) { + var r = this.items[n]; + if (r.instance != this.currentContainer && this.currentContainer && r.item[0] != this.currentItem[0])continue; + var i = this.options.toleranceElement ? e(this.options.toleranceElement, r.item) : r.item; + t || (r.width = i.outerWidth(), r.height = i.outerHeight()); + var s = i.offset(); + r.left = s.left, r.top = s.top + } + if (this.options.custom && this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this); else for (var n = this.containers.length - 1; n >= 0; n--) { + var s = this.containers[n].element.offset(); + this.containers[n].containerCache.left = s.left, this.containers[n].containerCache.top = s.top, this.containers[n].containerCache.width = this.containers[n].element.outerWidth(), this.containers[n].containerCache.height = this.containers[n].element.outerHeight() + } + return this + }, _createPlaceholder: function (t) { + t = t || this; + var n = t.options; + if (!n.placeholder || n.placeholder.constructor == String) { + var r = n.placeholder; + n.placeholder = {element: function () { + var n = e(document.createElement(t.currentItem[0].nodeName)).addClass(r || t.currentItem[0].className + " ui-sortable-placeholder").removeClass("ui-sortable-helper")[0]; + return r || (n.style.visibility = "hidden"), n + }, update: function (e, i) { + if (r && !n.forcePlaceholderSize)return; + i.height() || i.height(t.currentItem.innerHeight() - parseInt(t.currentItem.css("paddingTop") || 0, 10) - parseInt(t.currentItem.css("paddingBottom") || 0, 10)), i.width() || i.width(t.currentItem.innerWidth() - parseInt(t.currentItem.css("paddingLeft") || 0, 10) - parseInt(t.currentItem.css("paddingRight") || 0, 10)) + }} + } + t.placeholder = e(n.placeholder.element.call(t.element, t.currentItem)), t.currentItem.after(t.placeholder), n.placeholder.update(t, t.placeholder) + }, _contactContainers: function (t) { + var n = null, r = null; + for (var i = this.containers.length - 1; i >= 0; i--) { + if (e.contains(this.currentItem[0], this.containers[i].element[0]))continue; + if (this._intersectsWith(this.containers[i].containerCache)) { + if (n && e.contains(this.containers[i].element[0], n.element[0]))continue; + n = this.containers[i], r = i + } else this.containers[i].containerCache.over && (this.containers[i]._trigger("out", t, this._uiHash(this)), this.containers[i].containerCache.over = 0) + } + if (!n)return; + if (this.containers.length === 1)this.containers[r]._trigger("over", t, this._uiHash(this)), this.containers[r].containerCache.over = 1; else { + var s = 1e4, o = null, u = this.containers[r].floating ? "left" : "top", a = this.containers[r].floating ? "width" : "height", f = this.positionAbs[u] + this.offset.click[u]; + for (var l = this.items.length - 1; l >= 0; l--) { + if (!e.contains(this.containers[r].element[0], this.items[l].item[0]))continue; + if (this.items[l].item[0] == this.currentItem[0])continue; + var c = this.items[l].item.offset()[u], h = !1; + Math.abs(c - f) > Math.abs(c + this.items[l][a] - f) && (h = !0, c += this.items[l][a]), Math.abs(c - f) < s && (s = Math.abs(c - f), o = this.items[l], this.direction = h ? "up" : "down") + } + if (!o && !this.options.dropOnEmpty)return; + this.currentContainer = this.containers[r], o ? this._rearrange(t, o, null, !0) : this._rearrange(t, null, this.containers[r].element, !0), this._trigger("change", t, this._uiHash()), this.containers[r]._trigger("change", t, this._uiHash(this)), this.options.placeholder.update(this.currentContainer, this.placeholder), this.containers[r]._trigger("over", t, this._uiHash(this)), this.containers[r].containerCache.over = 1 + } + }, _createHelper: function (t) { + var n = this.options, r = e.isFunction(n.helper) ? e(n.helper.apply(this.element[0], [t, this.currentItem])) : n.helper == "clone" ? this.currentItem.clone() : this.currentItem; + return r.parents("body").length || e(n.appendTo != "parent" ? n.appendTo : this.currentItem[0].parentNode)[0].appendChild(r[0]), r[0] == this.currentItem[0] && (this._storedCSS = {width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left")}), (r[0].style.width == "" || n.forceHelperSize) && r.width(this.currentItem.width()), (r[0].style.height == "" || n.forceHelperSize) && r.height(this.currentItem.height()), r + }, _adjustOffsetFromHelper: function (t) { + typeof t == "string" && (t = t.split(" ")), e.isArray(t) && (t = {left: +t[0], top: +t[1] || 0}), "left"in t && (this.offset.click.left = t.left + this.margins.left), "right"in t && (this.offset.click.left = this.helperProportions.width - t.right + this.margins.left), "top"in t && (this.offset.click.top = t.top + this.margins.top), "bottom"in t && (this.offset.click.top = this.helperProportions.height - t.bottom + this.margins.top) + }, _getParentOffset: function () { + this.offsetParent = this.helper.offsetParent(); + var t = this.offsetParent.offset(); + this.cssPosition == "absolute" && this.scrollParent[0] != document && e.contains(this.scrollParent[0], this.offsetParent[0]) && (t.left += this.scrollParent.scrollLeft(), t.top += this.scrollParent.scrollTop()); + if (this.offsetParent[0] == document.body || this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == "html" && e.ui.ie)t = {top: 0, left: 0}; + return{top: t.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), left: t.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)} + }, _getRelativeOffset: function () { + if (this.cssPosition == "relative") { + var e = this.currentItem.position(); + return{top: e.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(), left: e.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft()} + } + return{top: 0, left: 0} + }, _cacheMargins: function () { + this.margins = {left: parseInt(this.currentItem.css("marginLeft"), 10) || 0, top: parseInt(this.currentItem.css("marginTop"), 10) || 0} + }, _cacheHelperProportions: function () { + this.helperProportions = {width: this.helper.outerWidth(), height: this.helper.outerHeight()} + }, _setContainment: function () { + var t = this.options; + t.containment == "parent" && (t.containment = this.helper[0].parentNode); + if (t.containment == "document" || t.containment == "window")this.containment = [0 - this.offset.relative.left - this.offset.parent.left, 0 - this.offset.relative.top - this.offset.parent.top, e(t.containment == "document" ? document : window).width() - this.helperProportions.width - this.margins.left, (e(t.containment == "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top]; + if (!/^(document|window|parent)$/.test(t.containment)) { + var n = e(t.containment)[0], r = e(t.containment).offset(), i = e(n).css("overflow") != "hidden"; + this.containment = [r.left + (parseInt(e(n).css("borderLeftWidth"), 10) || 0) + (parseInt(e(n).css("paddingLeft"), 10) || 0) - this.margins.left, r.top + (parseInt(e(n).css("borderTopWidth"), 10) || 0) + (parseInt(e(n).css("paddingTop"), 10) || 0) - this.margins.top, r.left + (i ? Math.max(n.scrollWidth, n.offsetWidth) : n.offsetWidth) - (parseInt(e(n).css("borderLeftWidth"), 10) || 0) - (parseInt(e(n).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left, r.top + (i ? Math.max(n.scrollHeight, n.offsetHeight) : n.offsetHeight) - (parseInt(e(n).css("borderTopWidth"), 10) || 0) - (parseInt(e(n).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top] + } + }, _convertPositionTo: function (t, n) { + n || (n = this.position); + var r = t == "absolute" ? 1 : -1, i = this.options, s = this.cssPosition != "absolute" || this.scrollParent[0] != document && !!e.contains(this.scrollParent[0], this.offsetParent[0]) ? this.scrollParent : this.offsetParent, o = /(html|body)/i.test(s[0].tagName); + return{top: n.top + this.offset.relative.top * r + this.offset.parent.top * r - (this.cssPosition == "fixed" ? -this.scrollParent.scrollTop() : o ? 0 : s.scrollTop()) * r, left: n.left + this.offset.relative.left * r + this.offset.parent.left * r - (this.cssPosition == "fixed" ? -this.scrollParent.scrollLeft() : o ? 0 : s.scrollLeft()) * r} + }, _generatePosition: function (t) { + var n = this.options, r = this.cssPosition != "absolute" || this.scrollParent[0] != document && !!e.contains(this.scrollParent[0], this.offsetParent[0]) ? this.scrollParent : this.offsetParent, i = /(html|body)/i.test(r[0].tagName); + this.cssPosition == "relative" && (this.scrollParent[0] == document || this.scrollParent[0] == this.offsetParent[0]) && (this.offset.relative = this._getRelativeOffset()); + var s = t.pageX, o = t.pageY; + if (this.originalPosition) { + this.containment && (t.pageX - this.offset.click.left < this.containment[0] && (s = this.containment[0] + this.offset.click.left), t.pageY - this.offset.click.top < this.containment[1] && (o = this.containment[1] + this.offset.click.top), t.pageX - this.offset.click.left > this.containment[2] && (s = this.containment[2] + this.offset.click.left), t.pageY - this.offset.click.top > this.containment[3] && (o = this.containment[3] + this.offset.click.top)); + if (n.grid) { + var u = this.originalPageY + Math.round((o - this.originalPageY) / n.grid[1]) * n.grid[1]; + o = this.containment ? u - this.offset.click.top < this.containment[1] || u - this.offset.click.top > this.containment[3] ? u - this.offset.click.top < this.containment[1] ? u + n.grid[1] : u - n.grid[1] : u : u; + var a = this.originalPageX + Math.round((s - this.originalPageX) / n.grid[0]) * n.grid[0]; + s = this.containment ? a - this.offset.click.left < this.containment[0] || a - this.offset.click.left > this.containment[2] ? a - this.offset.click.left < this.containment[0] ? a + n.grid[0] : a - n.grid[0] : a : a + } + } + return{top: o - this.offset.click.top - this.offset.relative.top - this.offset.parent.top + (this.cssPosition == "fixed" ? -this.scrollParent.scrollTop() : i ? 0 : r.scrollTop()), left: s - this.offset.click.left - this.offset.relative.left - this.offset.parent.left + (this.cssPosition == "fixed" ? -this.scrollParent.scrollLeft() : i ? 0 : r.scrollLeft())} + }, _rearrange: function (e, t, n, r) { + n ? n[0].appendChild(this.placeholder[0]) : t.item[0].parentNode.insertBefore(this.placeholder[0], this.direction == "down" ? t.item[0] : t.item[0].nextSibling), this.counter = this.counter ? ++this.counter : 1; + var i = this.counter; + this._delay(function () { + i == this.counter && this.refreshPositions(!r) + }) + }, _clear: function (t, n) { + this.reverting = !1; + var r = []; + !this._noFinalSort && this.currentItem.parent().length && this.placeholder.before(this.currentItem), this._noFinalSort = null; + if (this.helper[0] == this.currentItem[0]) { + for (var i in this._storedCSS)if (this._storedCSS[i] == "auto" || this._storedCSS[i] == "static")this._storedCSS[i] = ""; + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper") + } else this.currentItem.show(); + this.fromOutside && !n && r.push(function (e) { + this._trigger("receive", e, this._uiHash(this.fromOutside)) + }), (this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !n && r.push(function (e) { + this._trigger("update", e, this._uiHash()) + }), this !== this.currentContainer && (n || (r.push(function (e) { + this._trigger("remove", e, this._uiHash()) + }), r.push(function (e) { + return function (t) { + e._trigger("receive", t, this._uiHash(this)) + } + }.call(this, this.currentContainer)), r.push(function (e) { + return function (t) { + e._trigger("update", t, this._uiHash(this)) + } + }.call(this, this.currentContainer)))); + for (var i = this.containers.length - 1; i >= 0; i--)n || r.push(function (e) { + return function (t) { + e._trigger("deactivate", t, this._uiHash(this)) + } + }.call(this, this.containers[i])), this.containers[i].containerCache.over && (r.push(function (e) { + return function (t) { + e._trigger("out", t, this._uiHash(this)) + } + }.call(this, this.containers[i])), this.containers[i].containerCache.over = 0); + this._storedCursor && e("body").css("cursor", this._storedCursor), this._storedOpacity && this.helper.css("opacity", this._storedOpacity), this._storedZIndex && this.helper.css("zIndex", this._storedZIndex == "auto" ? "" : this._storedZIndex), this.dragging = !1; + if (this.cancelHelperRemoval) { + if (!n) { + this._trigger("beforeStop", t, this._uiHash()); + for (var i = 0; i < r.length; i++)r[i].call(this, t); + this._trigger("stop", t, this._uiHash()) + } + return this.fromOutside = !1, !1 + } + n || this._trigger("beforeStop", t, this._uiHash()), this.placeholder[0].parentNode.removeChild(this.placeholder[0]), this.helper[0] != this.currentItem[0] && this.helper.remove(), this.helper = null; + if (!n) { + for (var i = 0; i < r.length; i++)r[i].call(this, t); + this._trigger("stop", t, this._uiHash()) + } + return this.fromOutside = !1, !0 + }, _trigger: function () { + e.Widget.prototype._trigger.apply(this, arguments) === !1 && this.cancel() + }, _uiHash: function (t) { + var n = t || this; + return{helper: n.helper, placeholder: n.placeholder || e([]), position: n.position, originalPosition: n.originalPosition, offset: n.positionAbs, item: n.currentItem, sender: t ? t.element : null} + }}) +})(jQuery); +(function (e) { + function t(e) { + return function () { + var t = this.element.val(); + e.apply(this, arguments), this._refresh(), t !== this.element.val() && this._trigger("change") + } + } + + e.widget("ui.spinner", {version: "1.9.1", defaultElement: "", widgetEventPrefix: "spin", options: {culture: null, icons: {down: "ui-icon-triangle-1-s", up: "ui-icon-triangle-1-n"}, incremental: !0, max: null, min: null, numberFormat: null, page: 10, step: 1, change: null, spin: null, start: null, stop: null}, _create: function () { + this._setOption("max", this.options.max), this._setOption("min", this.options.min), this._setOption("step", this.options.step), this._value(this.element.val(), !0), this._draw(), this._on(this._events), this._refresh(), this._on(this.window, {beforeunload: function () { + this.element.removeAttr("autocomplete") + }}) + }, _getCreateOptions: function () { + var t = {}, n = this.element; + return e.each(["min", "max", "step"], function (e, r) { + var i = n.attr(r); + i !== undefined && i.length && (t[r] = i) + }), t + }, _events: {keydown: function (e) { + this._start(e) && this._keydown(e) && e.preventDefault() + }, keyup: "_stop", focus: function () { + this.previous = this.element.val() + }, blur: function (e) { + if (this.cancelBlur) { + delete this.cancelBlur; + return + } + this._refresh(), this.previous !== this.element.val() && this._trigger("change", e) + }, mousewheel: function (e, t) { + if (!t)return; + if (!this.spinning && !this._start(e))return!1; + this._spin((t > 0 ? 1 : -1) * this.options.step, e), clearTimeout(this.mousewheelTimer), this.mousewheelTimer = this._delay(function () { + this.spinning && this._stop(e) + }, 100), e.preventDefault() + }, "mousedown .ui-spinner-button": function (t) { + function r() { + var e = this.element[0] === this.document[0].activeElement; + e || (this.element.focus(), this.previous = n, this._delay(function () { + this.previous = n + })) + } + + var n; + n = this.element[0] === this.document[0].activeElement ? this.previous : this.element.val(), t.preventDefault(), r.call(this), this.cancelBlur = !0, this._delay(function () { + delete this.cancelBlur, r.call(this) + }); + if (this._start(t) === !1)return; + this._repeat(null, e(t.currentTarget).hasClass("ui-spinner-up") ? 1 : -1, t) + }, "mouseup .ui-spinner-button": "_stop", "mouseenter .ui-spinner-button": function (t) { + if (!e(t.currentTarget).hasClass("ui-state-active"))return; + if (this._start(t) === !1)return!1; + this._repeat(null, e(t.currentTarget).hasClass("ui-spinner-up") ? 1 : -1, t) + }, "mouseleave .ui-spinner-button": "_stop"}, _draw: function () { + var e = this.uiSpinner = this.element.addClass("ui-spinner-input").attr("autocomplete", "off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml()); + this.element.attr("role", "spinbutton"), this.buttons = e.find(".ui-spinner-button").attr("tabIndex", -1).button().removeClass("ui-corner-all"), this.buttons.height() > Math.ceil(e.height() * .5) && e.height() > 0 && e.height(e.height()), this.options.disabled && this.disable() + }, _keydown: function (t) { + var n = this.options, r = e.ui.keyCode; + switch (t.keyCode) { + case r.UP: + return this._repeat(null, 1, t), !0; + case r.DOWN: + return this._repeat(null, -1, t), !0; + case r.PAGE_UP: + return this._repeat(null, n.page, t), !0; + case r.PAGE_DOWN: + return this._repeat(null, -n.page, t), !0 + } + return!1 + }, _uiSpinnerHtml: function () { + return"" + }, _buttonHtml: function () { + return"" + "" + "" + "" + "" + }, _start: function (e) { + return!this.spinning && this._trigger("start", e) === !1 ? !1 : (this.counter || (this.counter = 1), this.spinning = !0, !0) + }, _repeat: function (e, t, n) { + e = e || 500, clearTimeout(this.timer), this.timer = this._delay(function () { + this._repeat(40, t, n) + }, e), this._spin(t * this.options.step, n) + }, _spin: function (e, t) { + var n = this.value() || 0; + this.counter || (this.counter = 1), n = this._adjustValue(n + e * this._increment(this.counter)); + if (!this.spinning || this._trigger("spin", t, {value: n}) !== !1)this._value(n), this.counter++ + }, _increment: function (t) { + var n = this.options.incremental; + return n ? e.isFunction(n) ? n(t) : Math.floor(t * t * t / 5e4 - t * t / 500 + 17 * t / 200 + 1) : 1 + }, _precision: function () { + var e = this._precisionOf(this.options.step); + return this.options.min !== null && (e = Math.max(e, this._precisionOf(this.options.min))), e + }, _precisionOf: function (e) { + var t = e.toString(), n = t.indexOf("."); + return n === -1 ? 0 : t.length - n - 1 + }, _adjustValue: function (e) { + var t, n, r = this.options; + return t = r.min !== null ? r.min : 0, n = e - t, n = Math.round(n / r.step) * r.step, e = t + n, e = parseFloat(e.toFixed(this._precision())), r.max !== null && e > r.max ? r.max : r.min !== null && e < r.min ? r.min : e + }, _stop: function (e) { + if (!this.spinning)return; + clearTimeout(this.timer), clearTimeout(this.mousewheelTimer), this.counter = 0, this.spinning = !1, this._trigger("stop", e) + }, _setOption: function (e, t) { + if (e === "culture" || e === "numberFormat") { + var n = this._parse(this.element.val()); + this.options[e] = t, this.element.val(this._format(n)); + return + } + (e === "max" || e === "min" || e === "step") && typeof t == "string" && (t = this._parse(t)), this._super(e, t), e === "disabled" && (t ? (this.element.prop("disabled", !0), this.buttons.button("disable")) : (this.element.prop("disabled", !1), this.buttons.button("enable"))) + }, _setOptions: t(function (e) { + this._super(e), this._value(this.element.val()) + }), _parse: function (e) { + return typeof e == "string" && e !== "" && (e = window.Globalize && this.options.numberFormat ? Globalize.parseFloat(e, 10, this.options.culture) : +e), e === "" || isNaN(e) ? null : e + }, _format: function (e) { + return e === "" ? "" : window.Globalize && this.options.numberFormat ? Globalize.format(e, this.options.numberFormat, this.options.culture) : e + }, _refresh: function () { + this.element.attr({"aria-valuemin": this.options.min, "aria-valuemax": this.options.max, "aria-valuenow": this._parse(this.element.val())}) + }, _value: function (e, t) { + var n; + e !== "" && (n = this._parse(e), n !== null && (t || (n = this._adjustValue(n)), e = this._format(n))), this.element.val(e), this._refresh() + }, _destroy: function () { + this.element.removeClass("ui-spinner-input").prop("disabled", !1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"), this.uiSpinner.replaceWith(this.element) + }, stepUp: t(function (e) { + this._stepUp(e) + }), _stepUp: function (e) { + this._spin((e || 1) * this.options.step) + }, stepDown: t(function (e) { + this._stepDown(e) + }), _stepDown: function (e) { + this._spin((e || 1) * -this.options.step) + }, pageUp: t(function (e) { + this._stepUp((e || 1) * this.options.page) + }), pageDown: t(function (e) { + this._stepDown((e || 1) * this.options.page) + }), value: function (e) { + if (!arguments.length)return this._parse(this.element.val()); + t(this._value).call(this, e) + }, widget: function () { + return this.uiSpinner + }}) +})(jQuery); +(function (e, t) { + function i() { + return++n + } + + function s(e) { + return e.hash.length > 1 && e.href.replace(r, "") === location.href.replace(r, "") + } + + var n = 0, r = /#.*$/; + e.widget("ui.tabs", {version: "1.9.1", delay: 300, options: {active: null, collapsible: !1, event: "click", heightStyle: "content", hide: null, show: null, activate: null, beforeActivate: null, beforeLoad: null, load: null}, _create: function () { + var t = this, n = this.options, r = n.active, i = location.hash.substring(1); + this.running = !1, this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible", n.collapsible).delegate(".ui-tabs-nav > li", "mousedown" + this.eventNamespace,function (t) { + e(this).is(".ui-state-disabled") && t.preventDefault() + }).delegate(".ui-tabs-anchor", "focus" + this.eventNamespace, function () { + e(this).closest("li").is(".ui-state-disabled") && this.blur() + }), this._processTabs(); + if (r === null) { + i && this.tabs.each(function (t, n) { + if (e(n).attr("aria-controls") === i)return r = t, !1 + }), r === null && (r = this.tabs.index(this.tabs.filter(".ui-tabs-active"))); + if (r === null || r === -1)r = this.tabs.length ? 0 : !1 + } + r !== !1 && (r = this.tabs.index(this.tabs.eq(r)), r === -1 && (r = n.collapsible ? !1 : 0)), n.active = r, !n.collapsible && n.active === !1 && this.anchors.length && (n.active = 0), e.isArray(n.disabled) && (n.disabled = e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"), function (e) { + return t.tabs.index(e) + }))).sort()), this.options.active !== !1 && this.anchors.length ? this.active = this._findActive(this.options.active) : this.active = e(), this._refresh(), this.active.length && this.load(n.active) + }, _getCreateEventData: function () { + return{tab: this.active, panel: this.active.length ? this._getPanelForTab(this.active) : e()} + }, _tabKeydown: function (t) { + var n = e(this.document[0].activeElement).closest("li"), r = this.tabs.index(n), i = !0; + if (this._handlePageNav(t))return; + switch (t.keyCode) { + case e.ui.keyCode.RIGHT: + case e.ui.keyCode.DOWN: + r++; + break; + case e.ui.keyCode.UP: + case e.ui.keyCode.LEFT: + i = !1, r--; + break; + case e.ui.keyCode.END: + r = this.anchors.length - 1; + break; + case e.ui.keyCode.HOME: + r = 0; + break; + case e.ui.keyCode.SPACE: + t.preventDefault(), clearTimeout(this.activating), this._activate(r); + return; + case e.ui.keyCode.ENTER: + t.preventDefault(), clearTimeout(this.activating), this._activate(r === this.options.active ? !1 : r); + return; + default: + return + } + t.preventDefault(), clearTimeout(this.activating), r = this._focusNextTab(r, i), t.ctrlKey || (n.attr("aria-selected", "false"), this.tabs.eq(r).attr("aria-selected", "true"), this.activating = this._delay(function () { + this.option("active", r) + }, this.delay)) + }, _panelKeydown: function (t) { + if (this._handlePageNav(t))return; + t.ctrlKey && t.keyCode === e.ui.keyCode.UP && (t.preventDefault(), this.active.focus()) + }, _handlePageNav: function (t) { + if (t.altKey && t.keyCode === e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active - 1, !1)), !0; + if (t.altKey && t.keyCode === e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active + 1, !0)), !0 + }, _findNextTab: function (t, n) { + function i() { + return t > r && (t = 0), t < 0 && (t = r), t + } + + var r = this.tabs.length - 1; + while (e.inArray(i(), this.options.disabled) !== -1)t = n ? t + 1 : t - 1; + return t + }, _focusNextTab: function (e, t) { + return e = this._findNextTab(e, t), this.tabs.eq(e).focus(), e + }, _setOption: function (e, t) { + if (e === "active") { + this._activate(t); + return + } + if (e === "disabled") { + this._setupDisabled(t); + return + } + this._super(e, t), e === "collapsible" && (this.element.toggleClass("ui-tabs-collapsible", t), !t && this.options.active === !1 && this._activate(0)), e === "event" && this._setupEvents(t), e === "heightStyle" && this._setupHeightStyle(t) + }, _tabId: function (e) { + return e.attr("aria-controls") || "ui-tabs-" + i() + }, _sanitizeSelector: function (e) { + return e ? e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&") : "" + }, refresh: function () { + var t = this.options, n = this.tablist.children(":has(a[href])"); + t.disabled = e.map(n.filter(".ui-state-disabled"), function (e) { + return n.index(e) + }), this._processTabs(), t.active === !1 || !this.anchors.length ? (t.active = !1, this.active = e()) : this.active.length && !e.contains(this.tablist[0], this.active[0]) ? this.tabs.length === t.disabled.length ? (t.active = !1, this.active = e()) : this._activate(this._findNextTab(Math.max(0, t.active - 1), !1)) : t.active = this.tabs.index(this.active), this._refresh() + }, _refresh: function () { + this._setupDisabled(this.options.disabled), this._setupEvents(this.options.event), this._setupHeightStyle(this.options.heightStyle), this.tabs.not(this.active).attr({"aria-selected": "false", tabIndex: -1}), this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded": "false", "aria-hidden": "true"}), this.active.length ? (this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected": "true", tabIndex: 0}), this._getPanelForTab(this.active).show().attr({"aria-expanded": "true", "aria-hidden": "false"})) : this.tabs.eq(0).attr("tabIndex", 0) + }, _processTabs: function () { + var t = this; + this.tablist = this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role", "tablist"), this.tabs = this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role: "tab", tabIndex: -1}), this.anchors = this.tabs.map(function () { + return e("a", this)[0] + }).addClass("ui-tabs-anchor").attr({role: "presentation", tabIndex: -1}), this.panels = e(), this.anchors.each(function (n, r) { + var i, o, u, a = e(r).uniqueId().attr("id"), f = e(r).closest("li"), l = f.attr("aria-controls"); + s(r) ? (i = r.hash, o = t.element.find(t._sanitizeSelector(i))) : (u = t._tabId(f), i = "#" + u, o = t.element.find(i), o.length || (o = t._createPanel(u), o.insertAfter(t.panels[n - 1] || t.tablist)), o.attr("aria-live", "polite")), o.length && (t.panels = t.panels.add(o)), l && f.data("ui-tabs-aria-controls", l), f.attr({"aria-controls": i.substring(1), "aria-labelledby": a}), o.attr("aria-labelledby", a) + }), this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role", "tabpanel") + }, _getList: function () { + return this.element.find("ol,ul").eq(0) + }, _createPanel: function (t) { + return e("
    ").attr("id", t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy", !0) + }, _setupDisabled: function (t) { + e.isArray(t) && (t.length ? t.length === this.anchors.length && (t = !0) : t = !1); + for (var n = 0, r; r = this.tabs[n]; n++)t === !0 || e.inArray(n, t) !== -1 ? e(r).addClass("ui-state-disabled").attr("aria-disabled", "true") : e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled"); + this.options.disabled = t + }, _setupEvents: function (t) { + var n = {click: function (e) { + e.preventDefault() + }}; + t && e.each(t.split(" "), function (e, t) { + n[t] = "_eventHandler" + }), this._off(this.anchors.add(this.tabs).add(this.panels)), this._on(this.anchors, n), this._on(this.tabs, {keydown: "_tabKeydown"}), this._on(this.panels, {keydown: "_panelKeydown"}), this._focusable(this.tabs), this._hoverable(this.tabs) + }, _setupHeightStyle: function (t) { + var n, r, i = this.element.parent(); + t === "fill" ? (e.support.minHeight || (r = i.css("overflow"), i.css("overflow", "hidden")), n = i.height(), this.element.siblings(":visible").each(function () { + var t = e(this), r = t.css("position"); + if (r === "absolute" || r === "fixed")return; + n -= t.outerHeight(!0) + }), r && i.css("overflow", r), this.element.children().not(this.panels).each(function () { + n -= e(this).outerHeight(!0) + }), this.panels.each(function () { + e(this).height(Math.max(0, n - e(this).innerHeight() + e(this).height())) + }).css("overflow", "auto")) : t === "auto" && (n = 0, this.panels.each(function () { + n = Math.max(n, e(this).height("").height()) + }).height(n)) + }, _eventHandler: function (t) { + var n = this.options, r = this.active, i = e(t.currentTarget), s = i.closest("li"), o = s[0] === r[0], u = o && n.collapsible, a = u ? e() : this._getPanelForTab(s), f = r.length ? this._getPanelForTab(r) : e(), l = {oldTab: r, oldPanel: f, newTab: u ? e() : s, newPanel: a}; + t.preventDefault(); + if (s.hasClass("ui-state-disabled") || s.hasClass("ui-tabs-loading") || this.running || o && !n.collapsible || this._trigger("beforeActivate", t, l) === !1)return; + n.active = u ? !1 : this.tabs.index(s), this.active = o ? e() : s, this.xhr && this.xhr.abort(), !f.length && !a.length && e.error("jQuery UI Tabs: Mismatching fragment identifier."), a.length && this.load(this.tabs.index(s), t), this._toggle(t, l) + }, _toggle: function (t, n) { + function o() { + r.running = !1, r._trigger("activate", t, n) + } + + function u() { + n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"), i.length && r.options.show ? r._show(i, r.options.show, o) : (i.show(), o()) + } + + var r = this, i = n.newPanel, s = n.oldPanel; + this.running = !0, s.length && this.options.hide ? this._hide(s, this.options.hide, function () { + n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"), u() + }) : (n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"), s.hide(), u()), s.attr({"aria-expanded": "false", "aria-hidden": "true"}), n.oldTab.attr("aria-selected", "false"), i.length && s.length ? n.oldTab.attr("tabIndex", -1) : i.length && this.tabs.filter(function () { + return e(this).attr("tabIndex") === 0 + }).attr("tabIndex", -1), i.attr({"aria-expanded": "true", "aria-hidden": "false"}), n.newTab.attr({"aria-selected": "true", tabIndex: 0}) + }, _activate: function (t) { + var n, r = this._findActive(t); + if (r[0] === this.active[0])return; + r.length || (r = this.active), n = r.find(".ui-tabs-anchor")[0], this._eventHandler({target: n, currentTarget: n, preventDefault: e.noop}) + }, _findActive: function (t) { + return t === !1 ? e() : this.tabs.eq(t) + }, _getIndex: function (e) { + return typeof e == "string" && (e = this.anchors.index(this.anchors.filter("[href$='" + e + "']"))), e + }, _destroy: function () { + this.xhr && this.xhr.abort(), this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"), this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"), this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(), this.tabs.add(this.panels).each(function () { + e.data(this, "ui-tabs-destroy") ? e(this).remove() : e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role") + }), this.tabs.each(function () { + var t = e(this), n = t.data("ui-tabs-aria-controls"); + n ? t.attr("aria-controls", n) : t.removeAttr("aria-controls") + }), this.options.heightStyle !== "content" && this.panels.css("height", "") + }, enable: function (n) { + var r = this.options.disabled; + if (r === !1)return; + n === t ? r = !1 : (n = this._getIndex(n), e.isArray(r) ? r = e.map(r, function (e) { + return e !== n ? e : null + }) : r = e.map(this.tabs, function (e, t) { + return t !== n ? t : null + })), this._setupDisabled(r) + }, disable: function (n) { + var r = this.options.disabled; + if (r === !0)return; + if (n === t)r = !0; else { + n = this._getIndex(n); + if (e.inArray(n, r) !== -1)return; + e.isArray(r) ? r = e.merge([n], r).sort() : r = [n] + } + this._setupDisabled(r) + }, load: function (t, n) { + t = this._getIndex(t); + var r = this, i = this.tabs.eq(t), o = i.find(".ui-tabs-anchor"), u = this._getPanelForTab(i), a = {tab: i, panel: u}; + if (s(o[0]))return; + this.xhr = e.ajax(this._ajaxSettings(o, n, a)), this.xhr && this.xhr.statusText !== "canceled" && (i.addClass("ui-tabs-loading"), u.attr("aria-busy", "true"), this.xhr.success(function (e) { + setTimeout(function () { + u.html(e), r._trigger("load", n, a) + }, 1) + }).complete(function (e, t) { + setTimeout(function () { + t === "abort" && r.panels.stop(!1, !0), i.removeClass("ui-tabs-loading"), u.removeAttr("aria-busy"), e === r.xhr && delete r.xhr + }, 1) + })) + }, _ajaxSettings: function (t, n, r) { + var i = this; + return{url: t.attr("href"), beforeSend: function (t, s) { + return i._trigger("beforeLoad", n, e.extend({jqXHR: t, ajaxSettings: s}, r)) + }} + }, _getPanelForTab: function (t) { + var n = e(t).attr("aria-controls"); + return this.element.find(this._sanitizeSelector("#" + n)) + }}), e.uiBackCompat !== !1 && (e.ui.tabs.prototype._ui = function (e, t) { + return{tab: e, panel: t, index: this.anchors.index(e)} + }, e.widget("ui.tabs", e.ui.tabs, {url: function (e, t) { + this.anchors.eq(e).attr("href", t) + }}), e.widget("ui.tabs", e.ui.tabs, {options: {ajaxOptions: null, cache: !1}, _create: function () { + this._super(); + var t = this; + this._on({tabsbeforeload: function (n, r) { + if (e.data(r.tab[0], "cache.tabs")) { + n.preventDefault(); + return + } + r.jqXHR.success(function () { + t.options.cache && e.data(r.tab[0], "cache.tabs", !0) + }) + }}) + }, _ajaxSettings: function (t, n, r) { + var i = this.options.ajaxOptions; + return e.extend({}, i, {error: function (e, t) { + try { + i.error(e, t, r.tab.closest("li").index(), r.tab[0]) + } catch (n) { + } + }}, this._superApply(arguments)) + }, _setOption: function (e, t) { + e === "cache" && t === !1 && this.anchors.removeData("cache.tabs"), this._super(e, t) + }, _destroy: function () { + this.anchors.removeData("cache.tabs"), this._super() + }, url: function (e) { + this.anchors.eq(e).removeData("cache.tabs"), this._superApply(arguments) + }}), e.widget("ui.tabs", e.ui.tabs, {abort: function () { + this.xhr && this.xhr.abort() + }}), e.widget("ui.tabs", e.ui.tabs, {options: {spinner: "Loading…"}, _create: function () { + this._super(), this._on({tabsbeforeload: function (e, t) { + if (e.target !== this.element[0] || !this.options.spinner)return; + var n = t.tab.find("span"), r = n.html(); + n.html(this.options.spinner), t.jqXHR.complete(function () { + n.html(r) + }) + }}) + }}), e.widget("ui.tabs", e.ui.tabs, {options: {enable: null, disable: null}, enable: function (t) { + var n = this.options, r; + if (t && n.disabled === !0 || e.isArray(n.disabled) && e.inArray(t, n.disabled) !== -1)r = !0; + this._superApply(arguments), r && this._trigger("enable", null, this._ui(this.anchors[t], this.panels[t])) + }, disable: function (t) { + var n = this.options, r; + if (t && n.disabled === !1 || e.isArray(n.disabled) && e.inArray(t, n.disabled) === -1)r = !0; + this._superApply(arguments), r && this._trigger("disable", null, this._ui(this.anchors[t], this.panels[t])) + }}), e.widget("ui.tabs", e.ui.tabs, {options: {add: null, remove: null, tabTemplate: "
  • #{label}
  • "}, add: function (n, r, i) { + i === t && (i = this.anchors.length); + var s, o, u = this.options, a = e(u.tabTemplate.replace(/#\{href\}/g, n).replace(/#\{label\}/g, r)), f = n.indexOf("#") ? this._tabId(a) : n.replace("#", ""); + return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy", !0), a.attr("aria-controls", f), s = i >= this.tabs.length, o = this.element.find("#" + f), o.length || (o = this._createPanel(f), s ? i > 0 ? o.insertAfter(this.panels.eq(-1)) : o.appendTo(this.element) : o.insertBefore(this.panels[i])), o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(), s ? a.appendTo(this.tablist) : a.insertBefore(this.tabs[i]), u.disabled = e.map(u.disabled, function (e) { + return e >= i ? ++e : e + }), this.refresh(), this.tabs.length === 1 && u.active === !1 && this.option("active", 0), this._trigger("add", null, this._ui(this.anchors[i], this.panels[i])), this + }, remove: function (t) { + t = this._getIndex(t); + var n = this.options, r = this.tabs.eq(t).remove(), i = this._getPanelForTab(r).remove(); + return r.hasClass("ui-tabs-active") && this.anchors.length > 2 && this._activate(t + (t + 1 < this.anchors.length ? 1 : -1)), n.disabled = e.map(e.grep(n.disabled, function (e) { + return e !== t + }), function (e) { + return e >= t ? --e : e + }), this.refresh(), this._trigger("remove", null, this._ui(r.find("a")[0], i[0])), this + }}), e.widget("ui.tabs", e.ui.tabs, {length: function () { + return this.anchors.length + }}), e.widget("ui.tabs", e.ui.tabs, {options: {idPrefix: "ui-tabs-"}, _tabId: function (t) { + var n = t.is("li") ? t.find("a[href]") : t; + return n = n[0], e(n).closest("li").attr("aria-controls") || n.title && n.title.replace(/\s/g, "_").replace(/[^\w\u00c0-\uFFFF\-]/g, "") || this.options.idPrefix + i() + }}), e.widget("ui.tabs", e.ui.tabs, {options: {panelTemplate: "
    "}, _createPanel: function (t) { + return e(this.options.panelTemplate).attr("id", t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy", !0) + }}), e.widget("ui.tabs", e.ui.tabs, {_create: function () { + var e = this.options; + e.active === null && e.selected !== t && (e.active = e.selected === -1 ? !1 : e.selected), this._super(), e.selected = e.active, e.selected === !1 && (e.selected = -1) + }, _setOption: function (e, t) { + if (e !== "selected")return this._super(e, t); + var n = this.options; + this._super("active", t === -1 ? !1 : t), n.selected = n.active, n.selected === !1 && (n.selected = -1) + }, _eventHandler: function () { + this._superApply(arguments), this.options.selected = this.options.active, this.options.selected === !1 && (this.options.selected = -1) + }}), e.widget("ui.tabs", e.ui.tabs, {options: {show: null, select: null}, _create: function () { + this._super(), this.options.active !== !1 && this._trigger("show", null, this._ui(this.active.find(".ui-tabs-anchor")[0], this._getPanelForTab(this.active)[0])) + }, _trigger: function (e, t, n) { + var r = this._superApply(arguments); + return r ? (e === "beforeActivate" && n.newTab.length ? r = this._super("select", t, {tab: n.newTab.find(".ui-tabs-anchor")[0], panel: n.newPanel[0], index: n.newTab.closest("li").index()}) : e === "activate" && n.newTab.length && (r = this._super("show", t, {tab: n.newTab.find(".ui-tabs-anchor")[0], panel: n.newPanel[0], index: n.newTab.closest("li").index()})), r) : !1 + }}), e.widget("ui.tabs", e.ui.tabs, {select: function (e) { + e = this._getIndex(e); + if (e === -1) { + if (!this.options.collapsible || this.options.selected === -1)return; + e = this.options.selected + } + this.anchors.eq(e).trigger(this.options.event + this.eventNamespace) + }}), function () { + var t = 0; + e.widget("ui.tabs", e.ui.tabs, {options: {cookie: null}, _create: function () { + var e = this.options, t; + e.active == null && e.cookie && (t = parseInt(this._cookie(), 10), t === -1 && (t = !1), e.active = t), this._super() + }, _cookie: function (n) { + var r = [this.cookie || (this.cookie = this.options.cookie.name || "ui-tabs-" + ++t)]; + return arguments.length && (r.push(n === !1 ? -1 : n), r.push(this.options.cookie)), e.cookie.apply(null, r) + }, _refresh: function () { + this._super(), this.options.cookie && this._cookie(this.options.active, this.options.cookie) + }, _eventHandler: function () { + this._superApply(arguments), this.options.cookie && this._cookie(this.options.active, this.options.cookie) + }, _destroy: function () { + this._super(), this.options.cookie && this._cookie(null, this.options.cookie) + }}) + }(), e.widget("ui.tabs", e.ui.tabs, {_trigger: function (t, n, r) { + var i = e.extend({}, r); + return t === "load" && (i.panel = i.panel[0], i.tab = i.tab.find(".ui-tabs-anchor")[0]), this._super(t, n, i) + }}), e.widget("ui.tabs", e.ui.tabs, {options: {fx: null}, _getFx: function () { + var t, n, r = this.options.fx; + return r && (e.isArray(r) ? (t = r[0], n = r[1]) : t = n = r), r ? {show: n, hide: t} : null + }, _toggle: function (e, t) { + function o() { + n.running = !1, n._trigger("activate", e, t) + } + + function u() { + t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"), r.length && s.show ? r.animate(s.show, s.show.duration, function () { + o() + }) : (r.show(), o()) + } + + var n = this, r = t.newPanel, i = t.oldPanel, s = this._getFx(); + if (!s)return this._super(e, t); + n.running = !0, i.length && s.hide ? i.animate(s.hide, s.hide.duration, function () { + t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"), u() + }) : (t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"), i.hide(), u()) + }})) +})(jQuery); +(function (e) { + function n(t, n) { + var r = (t.attr("aria-describedby") || "").split(/\s+/); + r.push(n), t.data("ui-tooltip-id", n).attr("aria-describedby", e.trim(r.join(" "))) + } + + function r(t) { + var n = t.data("ui-tooltip-id"), r = (t.attr("aria-describedby") || "").split(/\s+/), i = e.inArray(n, r); + i !== -1 && r.splice(i, 1), t.removeData("ui-tooltip-id"), r = e.trim(r.join(" ")), r ? t.attr("aria-describedby", r) : t.removeAttr("aria-describedby") + } + + var t = 0; + e.widget("ui.tooltip", {version: "1.9.1", options: {content: function () { + return e(this).attr("title") + }, hide: !0, items: "[title]:not([disabled])", position: {my: "left top+15", at: "left bottom", collision: "flipfit flipfit"}, show: !0, tooltipClass: null, track: !1, close: null, open: null}, _create: function () { + this._on({mouseover: "open", focusin: "open"}), this.tooltips = {}, this.parents = {}, this.options.disabled && this._disable() + }, _setOption: function (t, n) { + var r = this; + if (t === "disabled") { + this[n ? "_disable" : "_enable"](), this.options[t] = n; + return + } + this._super(t, n), t === "content" && e.each(this.tooltips, function (e, t) { + r._updateContent(t) + }) + }, _disable: function () { + var t = this; + e.each(this.tooltips, function (n, r) { + var i = e.Event("blur"); + i.target = i.currentTarget = r[0], t.close(i, !0) + }), this.element.find(this.options.items).andSelf().each(function () { + var t = e(this); + t.is("[title]") && t.data("ui-tooltip-title", t.attr("title")).attr("title", "") + }) + }, _enable: function () { + this.element.find(this.options.items).andSelf().each(function () { + var t = e(this); + t.data("ui-tooltip-title") && t.attr("title", t.data("ui-tooltip-title")) + }) + }, open: function (t) { + var n = this, r = e(t ? t.target : this.element).closest(this.options.items); + if (!r.length)return; + if (this.options.track && r.data("ui-tooltip-id")) { + this._find(r).position(e.extend({of: r}, this.options.position)), this._off(this.document, "mousemove"); + return + } + r.attr("title") && r.data("ui-tooltip-title", r.attr("title")), r.data("tooltip-open", !0), t && t.type === "mouseover" && r.parents().each(function () { + var t; + e(this).data("tooltip-open") && (t = e.Event("blur"), t.target = t.currentTarget = this, n.close(t, !0)), this.title && (e(this).uniqueId(), n.parents[this.id] = {element: this, title: this.title}, this.title = "") + }), this._updateContent(r, t) + }, _updateContent: function (e, t) { + var n, r = this.options.content, i = this; + if (typeof r == "string")return this._open(t, e, r); + n = r.call(e[0], function (n) { + if (!e.data("tooltip-open"))return; + i._delay(function () { + this._open(t, e, n) + }) + }), n && this._open(t, e, n) + }, _open: function (t, r, i) { + function f(e) { + a.of = e; + if (s.is(":hidden"))return; + s.position(a) + } + + var s, o, u, a = e.extend({}, this.options.position); + if (!i)return; + s = this._find(r); + if (s.length) { + s.find(".ui-tooltip-content").html(i); + return + } + r.is("[title]") && (t && t.type === "mouseover" ? r.attr("title", "") : r.removeAttr("title")), s = this._tooltip(r), n(r, s.attr("id")), s.find(".ui-tooltip-content").html(i), this.options.track && t && /^mouse/.test(t.originalEvent.type) ? (this._on(this.document, {mousemove: f}), f(t)) : s.position(e.extend({of: r}, this.options.position)), s.hide(), this._show(s, this.options.show), this.options.show && this.options.show.delay && (u = setInterval(function () { + s.is(":visible") && (f(a.of), clearInterval(u)) + }, e.fx.interval)), this._trigger("open", t, {tooltip: s}), o = {keyup: function (t) { + if (t.keyCode === e.ui.keyCode.ESCAPE) { + var n = e.Event(t); + n.currentTarget = r[0], this.close(n, !0) + } + }, remove: function () { + this._removeTooltip(s) + }}; + if (!t || t.type === "mouseover")o.mouseleave = "close"; + if (!t || t.type === "focusin")o.focusout = "close"; + this._on(r, o) + }, close: function (t) { + var n = this, i = e(t ? t.currentTarget : this.element), s = this._find(i); + if (this.closing)return; + i.data("ui-tooltip-title") && i.attr("title", i.data("ui-tooltip-title")), r(i), s.stop(!0), this._hide(s, this.options.hide, function () { + n._removeTooltip(e(this)) + }), i.removeData("tooltip-open"), this._off(i, "mouseleave focusout keyup"), i[0] !== this.element[0] && this._off(i, "remove"), this._off(this.document, "mousemove"), t && t.type === "mouseleave" && e.each(this.parents, function (e, t) { + t.element.title = t.title, delete n.parents[e] + }), this.closing = !0, this._trigger("close", t, {tooltip: s}), this.closing = !1 + }, _tooltip: function (n) { + var r = "ui-tooltip-" + t++, i = e("
    ").attr({id: r, role: "tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content " + (this.options.tooltipClass || "")); + return e("
    ").addClass("ui-tooltip-content").appendTo(i), i.appendTo(this.document[0].body), e.fn.bgiframe && i.bgiframe(), this.tooltips[r] = n, i + }, _find: function (t) { + var n = t.data("ui-tooltip-id"); + return n ? e("#" + n) : e() + }, _removeTooltip: function (e) { + e.remove(), delete this.tooltips[e.attr("id")] + }, _destroy: function () { + var t = this; + e.each(this.tooltips, function (n, r) { + var i = e.Event("blur"); + i.target = i.currentTarget = r[0], t.close(i, !0), e("#" + n).remove(), r.data("ui-tooltip-title") && (r.attr("title", r.data("ui-tooltip-title")), r.removeData("ui-tooltip-title")) + }) + }}) +})(jQuery); \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/vendor/jquery.ui.widget.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/vendor/jquery.ui.widget.js new file mode 100644 index 0000000..f90bd95 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/assets/js/vendor/jquery.ui.widget.js @@ -0,0 +1,531 @@ +/* + * jQuery UI Widget 1.9.1+amd + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/jQuery.widget/ + */ + +(function (factory) { + if (typeof define === "function" && define.amd) { + // Register as an anonymous AMD module: + define(["jquery"], factory); + } else { + // Browser globals: + factory(jQuery); + } +}(function ($, undefined) { + + var uuid = 0, + slice = Array.prototype.slice, + _cleanData = $.cleanData; + $.cleanData = function (elems) { + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + try { + $(elem).triggerHandler("remove"); + // http://bugs.jquery.com/ticket/8235 + } catch (e) { + } + } + _cleanData(elems); + }; + + $.widget = function (name, base, prototype) { + var fullName, existingConstructor, constructor, basePrototype, + namespace = name.split(".")[ 0 ]; + + name = name.split(".")[ 1 ]; + fullName = namespace + "-" + name; + + if (!prototype) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName.toLowerCase() ] = function (elem) { + return !!$.data(elem, fullName); + }; + + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function (options, element) { + // allow instantiation without "new" keyword + if (!this._createWidget) { + return new constructor(options, element); + } + + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if (arguments.length) { + this._createWidget(options, element); + } + }; + // extend with the existing constructor to carry over any static properties + $.extend(constructor, existingConstructor, { + version: prototype.version, + // copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend({}, prototype), + // track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + }); + + basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend({}, basePrototype.options); + $.each(prototype, function (prop, value) { + if ($.isFunction(value)) { + prototype[ prop ] = (function () { + var _super = function () { + return base.prototype[ prop ].apply(this, arguments); + }, + _superApply = function (args) { + return base.prototype[ prop ].apply(this, args); + }; + return function () { + var __super = this._super, + __superApply = this._superApply, + returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply(this, arguments); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + })(); + } + }); + constructor.prototype = $.widget.extend(basePrototype, { + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: basePrototype.widgetEventPrefix || name + }, prototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + // TODO remove widgetBaseClass, see #8155 + widgetBaseClass: fullName, + widgetFullName: fullName + }); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if (existingConstructor) { + $.each(existingConstructor._childConstructors, function (i, child) { + var childPrototype = child.prototype; + + // redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget(childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto); + }); + // remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push(constructor); + } + + $.widget.bridge(name, constructor); + }; + + $.widget.extend = function (target) { + var input = slice.call(arguments, 1), + inputIndex = 0, + inputLength = input.length, + key, + value; + for (; inputIndex < inputLength; inputIndex++) { + for (key in input[ inputIndex ]) { + value = input[ inputIndex ][ key ]; + if (input[ inputIndex ].hasOwnProperty(key) && value !== undefined) { + // Clone objects + if ($.isPlainObject(value)) { + target[ key ] = $.isPlainObject(target[ key ]) ? + $.widget.extend({}, target[ key ], value) : + // Don't extend strings, arrays, etc. with objects + $.widget.extend({}, value); + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; + }; + + $.widget.bridge = function (name, object) { + var fullName = object.prototype.widgetFullName; + $.fn[ name ] = function (options) { + var isMethodCall = typeof options === "string", + args = slice.call(arguments, 1), + returnValue = this; + + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? + $.widget.extend.apply(null, [ options ].concat(args)) : + options; + + if (isMethodCall) { + this.each(function () { + var methodValue, + instance = $.data(this, fullName); + if (!instance) { + return $.error("cannot call methods on " + name + " prior to initialization; " + + "attempted to call method '" + options + "'"); + } + if (!$.isFunction(instance[options]) || options.charAt(0) === "_") { + return $.error("no such method '" + options + "' for " + name + " widget instance"); + } + methodValue = instance[ options ].apply(instance, args); + if (methodValue !== instance && methodValue !== undefined) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack(methodValue.get()) : + methodValue; + return false; + } + }); + } else { + this.each(function () { + var instance = $.data(this, fullName); + if (instance) { + instance.option(options || {})._init(); + } else { + new object(options, this); + } + }); + } + + return returnValue; + }; + }; + + $.Widget = function (/* options, element */) { + }; + $.Widget._childConstructors = []; + + $.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "
    ", + options: { + disabled: false, + + // callbacks + create: null + }, + _createWidget: function (options, element) { + element = $(element || this.defaultElement || this)[ 0 ]; + this.element = $(element); + this.uuid = uuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + this.options = $.widget.extend({}, + this.options, + this._getCreateOptions(), + options); + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + + if (element !== this) { + // 1.9 BC for #7810 + // TODO remove dual storage + $.data(element, this.widgetName, this); + $.data(element, this.widgetFullName, this); + this._on(this.element, { + remove: function (event) { + if (event.target === element) { + this.destroy(); + } + } + }); + this.document = $(element.style ? + // element within the document + element.ownerDocument : + // element is window or document + element.document || element); + this.window = $(this.document[0].defaultView || this.document[0].parentWindow); + } + + this._create(); + this._trigger("create", null, this._getCreateEventData()); + this._init(); + }, + _getCreateOptions: $.noop, + _getCreateEventData: $.noop, + _create: $.noop, + _init: $.noop, + + destroy: function () { + this._destroy(); + // we can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .unbind(this.eventNamespace) + // 1.9 BC for #7810 + // TODO remove dual storage + .removeData(this.widgetName) + .removeData(this.widgetFullName) + // support: jquery <1.6.3 + // http://bugs.jquery.com/ticket/9413 + .removeData($.camelCase(this.widgetFullName)); + this.widget() + .unbind(this.eventNamespace) + .removeAttr("aria-disabled") + .removeClass( + this.widgetFullName + "-disabled " + + "ui-state-disabled"); + + // clean up events and states + this.bindings.unbind(this.eventNamespace); + this.hoverable.removeClass("ui-state-hover"); + this.focusable.removeClass("ui-state-focus"); + }, + _destroy: $.noop, + + widget: function () { + return this.element; + }, + + option: function (key, value) { + var options = key, + parts, + curOption, + i; + + if (arguments.length === 0) { + // don't return a reference to the internal hash + return $.widget.extend({}, this.options); + } + + if (typeof key === "string") { + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split("."); + key = parts.shift(); + if (parts.length) { + curOption = options[ key ] = $.widget.extend({}, this.options[ key ]); + for (i = 0; i < parts.length - 1; i++) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if (value === undefined) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if (value === undefined) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions(options); + + return this; + }, + _setOptions: function (options) { + var key; + + for (key in options) { + this._setOption(key, options[ key ]); + } + + return this; + }, + _setOption: function (key, value) { + this.options[ key ] = value; + + if (key === "disabled") { + this.widget() + .toggleClass(this.widgetFullName + "-disabled ui-state-disabled", !!value) + .attr("aria-disabled", value); + this.hoverable.removeClass("ui-state-hover"); + this.focusable.removeClass("ui-state-focus"); + } + + return this; + }, + + enable: function () { + return this._setOption("disabled", false); + }, + disable: function () { + return this._setOption("disabled", true); + }, + + _on: function (element, handlers) { + var delegateElement, + instance = this; + // no element argument, shuffle and use this.element + if (!handlers) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + // accept selectors, DOM elements + element = delegateElement = $(element); + this.bindings = this.bindings.add(element); + } + + $.each(handlers, function (event, handler) { + function handlerProxy() { + // allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if (instance.options.disabled === true || + $(this).hasClass("ui-state-disabled")) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply(instance, arguments); + } + + // copy the guid so direct unbinding works + if (typeof handler !== "string") { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match(/^(\w+)\s*(.*)$/), + eventName = match[1] + instance.eventNamespace, + selector = match[2]; + if (selector) { + delegateElement.delegate(selector, eventName, handlerProxy); + } else { + element.bind(eventName, handlerProxy); + } + }); + }, + + _off: function (element, eventName) { + eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace; + element.unbind(eventName).undelegate(eventName); + }, + + _delay: function (handler, delay) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply(instance, arguments); + } + + var instance = this; + return setTimeout(handlerProxy, delay || 0); + }, + + _hoverable: function (element) { + this.hoverable = this.hoverable.add(element); + this._on(element, { + mouseenter: function (event) { + $(event.currentTarget).addClass("ui-state-hover"); + }, + mouseleave: function (event) { + $(event.currentTarget).removeClass("ui-state-hover"); + } + }); + }, + + _focusable: function (element) { + this.focusable = this.focusable.add(element); + this._on(element, { + focusin: function (event) { + $(event.currentTarget).addClass("ui-state-focus"); + }, + focusout: function (event) { + $(event.currentTarget).removeClass("ui-state-focus"); + } + }); + }, + + _trigger: function (type, event, data) { + var prop, orig, + callback = this.options[ type ]; + + data = data || {}; + event = $.Event(event); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // copy original event properties over to the new event + orig = event.originalEvent; + if (orig) { + for (prop in orig) { + if (!( prop in event )) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger(event, data); + return !( $.isFunction(callback) && + callback.apply(this.element[0], [ event ].concat(data)) === false || + event.isDefaultPrevented() ); + } + }; + + $.each({ show: "fadeIn", hide: "fadeOut" }, function (method, defaultEffect) { + $.Widget.prototype[ "_" + method ] = function (element, options, callback) { + if (typeof options === "string") { + options = { effect: options }; + } + var hasOptions, + effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + options = options || {}; + if (typeof options === "number") { + options = { duration: options }; + } + hasOptions = !$.isEmptyObject(options); + options.complete = callback; + if (options.delay) { + element.delay(options.delay); + } + if (hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] )) { + element[ method ](options); + } else if (effectName !== method && element[ effectName ]) { + element[ effectName ](options.duration, options.easing, callback); + } else { + element.queue(function (next) { + $(this)[ method ](); + if (callback) { + callback.call(element[ 0 ]); + } + next(); + }); + } + }; + }); + +// DEPRECATED + if ($.uiBackCompat !== false) { + $.Widget.prototype._getCreateOptions = function () { + return $.metadata && $.metadata.get(this.element[0])[ this.widgetName ]; + }; + } + +})); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/download.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/download.php new file mode 100644 index 0000000..58798e2 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/download.php @@ -0,0 +1,34 @@ + + diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/form.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/form.php new file mode 100644 index 0000000..eafac76 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/form.php @@ -0,0 +1,45 @@ + +url, 'post', $this->htmlOptions); ?> +
    +
    + + Add files... + hasModel()) : + echo CHtml::activeFileField($this->model, $this->attribute, $htmlOptions) . "\n"; else : + echo CHtml::fileField($name, $this->value, $htmlOptions) . "\n"; + endif; + ?> + + + + + +
    +
    + +
    +
    +
    +
    +
    + +
    +
    + +
    + + +
    +
    + + diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/upload.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/upload.php new file mode 100644 index 0000000..1bec204 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fileupload/views/upload.php @@ -0,0 +1,37 @@ + + diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/WhFineUploader.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/WhFineUploader.php new file mode 100644 index 0000000..21ce05b --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/WhFineUploader.php @@ -0,0 +1,175 @@ + + * @copyright Copyright © 2amigos.us 2013- + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @package YiiWheels.widgets.fileuploader + * @uses YiiWheels.helpers.WhHtml + */ +Yii::import('yiiwheels.helpers.WhHtml'); + +class WhFineUploader extends CInputWidget +{ + /** + * @var string upload action url + */ + public $uploadAction; + + /** + * @var string the HTML tag to render the uploader to + */ + public $tagName = 'div'; + + /** + * @var string text to display if javascript is disabled + */ + public $noScriptText; + + /** + * @var array the plugin options + */ + public $pluginOptions = array(); + + /** + * @var array the events + */ + public $events = array(); + + /** + * @var string which scenario we get the validation from + */ + public $scenario; + + /** + * @var array d + */ + protected $defaultOptions = array(); + + /** + * @throws CException + */ + public function init() + { + if ($this->uploadAction === null) { + throw new CException(Yii::t('zii', '"uploadAction" attribute cannot be blank')); + } + if ($this->noScriptText === null) { + $this->noScriptText = Yii::t('zii', "Please enable JavaScript to use file uploader."); + } + + $this->attachBehavior('ywplugin', array('class' => 'yiiwheels.behaviors.WhPlugin')); + + $this->initDefaultOptions(); + } + + /** + * Widget's run method + */ + public function run() + { + $this->renderTag(); + $this->registerClientScript(); + } + + /** + * Renders the tag where the button is going to be rendered + */ + public function renderTag() + { + echo CHtml::tag($this->tagName, $this->htmlOptions, '', true); + } + + /** + * Registers required client script for finuploader + */ + public function registerClientScript() + { + /* publish assets dir */ + $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'assets'; + $assetsUrl = $this->getAssetsUrl($path); + + /* @var $cs CClientScript */ + $cs = Yii::app()->getClientScript(); + + $script = YII_DEBUG ? 'jquery.fineuploader-3.2.js' : 'jquery.fineuploader-3.2.min.js'; + + $cs->registerCssFile($assetsUrl . '/css/fineuploader.css'); + $cs->registerScriptFile($assetsUrl . '/js/' . $script); + + /* initialize plugin */ + $selector = '#' . WhHtml::getOption('id', $this->htmlOptions, $this->getId()); + + $this->getApi()->registerPlugin( + 'fineUploader', + $selector, + CMap::mergeArray($this->defaultOptions, $this->pluginOptions) + ); + $this->getApi()->registerEvents($selector, $this->events); + } + + /** + * Sets up default options for the plugin + * - thanks https://github.com/anggiaj + */ + protected function initDefaultOptions() + { + list($name, $id) = $this->resolveNameID(); + + $this->htmlOptions = WhHtml::defaultOption('id', $id, $this->htmlOptions); + $this->htmlOptions = WhHtml::defaultOption('name', $name, $this->htmlOptions); + + + $this->defaultOptions = array( + 'request' => array( + 'endpoint' => $this->uploadAction, + 'inputName' => $name, + ), + 'validation' => $this->getValidator(), + 'messages' => array( + 'typeError' => Yii::t('zii', '{file} has an invalid extension. Valid extension(s): {extensions}.'), + 'sizeError' => Yii::t('zii', '{file} is too large, maximum file size is {sizeLimit}.'), + 'minSizeError' => Yii::t('zii', '{file} is too small, minimum file size is {minSizeLimit}.'), + 'emptyError:' => Yii::t('zii', '{file} is empty, please select files again without it.'), + 'noFilesError' => Yii::t('zii', 'No files to upload.'), + 'onLeave' => Yii::t( + 'zii', + 'The files are being uploaded, if you leave now the upload will be cancelled.' + ) + ), + ); + } + + /** + * @return array + */ + protected function getValidator() + { + $ret = array(); + if ($this->hasModel()) { + if ($this->scenario !== null) { + $originalScenario = $this->model->getScenario(); + $this->model->setScenario($this->scenario); + $validators = $this->model->getValidators($this->attribute); + $this->model->setScenario($originalScenario); + + } else { + $validators = $this->model->getValidators($this->attribute); + } + + // we are just looking for the first founded CFileValidator + foreach ($validators as $validator) { + if (is_a($validator, 'CFileValidator')) { + $ret = array( + 'allowedExtensions' => explode(',', str_replace(' ', '', $validator->types)), + 'sizeLimit' => $validator->maxSize, + 'minSizeLimit' => $validator->minSize, + ); + break; + } + } + } + return $ret; + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/css/fineuploader.css b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/css/fineuploader.css new file mode 100644 index 0000000..6732d23 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/css/fineuploader.css @@ -0,0 +1,174 @@ +/* + * Original version: 1.0 © 2010 Andrew Valums ( andrew(at)valums.com ) + * Current Maintainer (2.0+): 2012, Ray Nicholus ( fineuploader(at)garstasio.com ) + * + * Licensed under MIT license, GNU GPL 2 or later, GNU LGPL 2 or later, see license.txt. + */ +.qq-uploader { + position: relative; + width: 100%; +} + +.qq-upload-button { + display: block; + width: 105px; + padding: 7px 0; + text-align: center; + background: #880000; + border-bottom: 1px solid #DDD; + color: #FFF; +} + +.qq-upload-button-hover { + background: #CC0000; +} + +.qq-upload-button-focus { + outline: 1px dotted #000000; +} + +.qq-upload-drop-area, .qq-upload-extra-drop-area { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + min-height: 30px; + z-index: 2; + background: #FF9797; + text-align: center; +} + +.qq-upload-drop-area span { + display: block; + position: absolute; + top: 50%; + width: 100%; + margin-top: -8px; + font-size: 16px; +} + +.qq-upload-extra-drop-area { + position: relative; + margin-top: 50px; + font-size: 16px; + padding-top: 30px; + height: 20px; + min-height: 40px; +} + +.qq-upload-drop-area-active { + background: #FF7171; +} + +.qq-upload-list { + margin: 0; + padding: 0; + list-style: none; +} + +.qq-upload-list li { + margin: 0; + padding: 9px; + line-height: 15px; + font-size: 16px; + background-color: #FFF0BD; +} + +.qq-upload-file, .qq-upload-spinner, .qq-upload-size, .qq-upload-cancel, .qq-upload-retry, .qq-upload-failed-text, .qq-upload-finished { + margin-right: 12px; +} + +.qq-upload-file { +} + +.qq-upload-spinner { + display: inline-block; + background: url("../img/loading.gif"); + width: 15px; + height: 15px; + vertical-align: text-bottom; +} + +.qq-drop-processing { + display: none; +} + +.qq-drop-processing-spinner { + display: inline-block; + background: url("../img/processing.gif"); + width: 24px; + height: 24px; + vertical-align: text-bottom; +} + +.qq-upload-finished { + display: none; + width: 15px; + height: 15px; + vertical-align: text-bottom; +} + +.qq-upload-retry { + display: none; + color: #000000; +} + +.qq-upload-cancel { + color: #000000; +} + +.qq-upload-retryable .qq-upload-retry { + display: inline; +} + +.qq-upload-size, .qq-upload-cancel, .qq-upload-retry { + font-size: 12px; + font-weight: normal; +} + +.qq-upload-failed-text { + display: none; + font-style: italic; + font-weight: bold; +} + +.qq-upload-failed-icon { + display: none; + width: 15px; + height: 15px; + vertical-align: text-bottom; +} + +.qq-upload-fail .qq-upload-failed-text { + display: inline; +} + +.qq-upload-retrying .qq-upload-failed-text { + display: inline; + color: #D60000; +} + +.qq-upload-list li.qq-upload-success { + background-color: #5DA30C; + color: #FFFFFF; +} + +.qq-upload-list li.qq-upload-fail { + background-color: #D60000; + color: #FFFFFF; +} + +.qq-progress-bar { + background: -moz-linear-gradient(top, rgba(30, 87, 153, 1) 0%, rgba(41, 137, 216, 1) 50%, rgba(32, 124, 202, 1) 51%, rgba(125, 185, 232, 1) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(30, 87, 153, 1)), color-stop(50%, rgba(41, 137, 216, 1)), color-stop(51%, rgba(32, 124, 202, 1)), color-stop(100%, rgba(125, 185, 232, 1))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, rgba(30, 87, 153, 1) 0%, rgba(41, 137, 216, 1) 50%, rgba(32, 124, 202, 1) 51%, rgba(125, 185, 232, 1) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(30, 87, 153, 1) 0%, rgba(41, 137, 216, 1) 50%, rgba(32, 124, 202, 1) 51%, rgba(125, 185, 232, 1) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(30, 87, 153, 1) 0%, rgba(41, 137, 216, 1) 50%, rgba(32, 124, 202, 1) 51%, rgba(125, 185, 232, 1) 100%); /* IE10+ */ + background: linear-gradient(to bottom, rgba(30, 87, 153, 1) 0%, rgba(41, 137, 216, 1) 50%, rgba(32, 124, 202, 1) 51%, rgba(125, 185, 232, 1) 100%); /* W3C */ + width: 0%; + height: 15px; + border-radius: 6px; + margin-bottom: 3px; + display: none; +} diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/img/loading.gif b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/img/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..6fba77609ec50f9ab338a90d658e16bb05b8d206 GIT binary patch literal 1688 zcmb`{Z%i9?90u@T|8OmBp{1p?1LC6bjoZDt zkXep>N0_=eva4($!i&&_A= zW;rjn{OxjfHIq1=2=5CoTwNF*91gVyGpm_kvp>8yy0hlS_a|Ji)@kL>dI%ZU?-^tFX>XV|yhM;_kA{Hbj4_?z5yjh^aFnC>zj^ z_o#~Hj9!_H_*k7~=KW86b?g7){QF<}*1#h#Mg;I?KfvJ(Qn0`|`BAdFr+c0K))KhV z*VBp7xc^E2^r^{p+tmzG058~M{V~WRzNN315Fgk94t9hH^W?`#Bm#eA1pn#xrXL)h zI^;Ui`0^Wt{g;NKDbM;@HlU>SeVzx$S zD(zKa4PR~x=t+@VO553Pr?otfml2s$r5>svWlh@%v+uePKj_d>&Sdse`V8u3A-efVY*!3yWCkn;jGN z4p{|BeYkjFBuDAmvz64yq>ELiQR#^<2l$(TJ_(cKNgIz_Nhh1{G-^uptX@&fDfK2t z(V)gap5e@`c^bWergglzjkZ2b7t|ZiD2PIur&VL64kt(#wk%s zfpfc0(7HF(kPybcEeIz;ajkaEet4sf;8~k<7z?FDCO6U`$2I{oVnGgoggOchLhOqN zujBo1p!U0lG3Lc@doPaP9*MBWqJ6csgq&1;(|E<#M=8iVshFbW=dNn!XfpbUcOt5= zE9QQ%mv7-6?w%-TGfT~7?vfl`ue3$U8Hk1(Ar{J5VlbKLUbFb5$<}64dvvPYQY$gZ z-{o1=x%2J~N7H{eLJ-9RB~A-UI6@GPsO9tr(~w0oVGU3e5=_{g(8NjrC^SKdatd>N zZ_ojXLLvZ|&VD*8OgVP*-7I$V!nFk~4-nrk^8fCs{i$`wIdNfSjQ?CDCdQYDd}#4E zzO35eJ}t3O)RgwDxNBFV=}K*%X_Sk;Fy$B%yR;^qxMio+)4z}Q2rbDSRQTqiegkVMdcOh*)yl$90>MUHO; z$`puTM1;T!MiGo+m3fqAYLQvxXtjzut!L|YXxFvO(^-ylmi4qdoVq8Ac4uw>ME>Hx zocsO!zR&Zxvt0|GTSFoe9Yl!B<~B4nTzL0_!{wN~HyJw=vs$d>FO`q~c|5u=8u&$E z`rp$d!y^Wr0TW~4*6`T%v8gYo7Cpac;**Ks+TexJ3tT?e=kZNFn2Ha@)1OMOsjC_P zXgt;*3#<-Ie=|LDb|lgsxqa*Q!-o&i6ZkVfl;k+`^X!>Ro%83;zjs-6o^)Wvce| zZqW)6eWXI%a||6<_iJLECXwi6I=XNFG6NgG=#Yq4NL#MZ@>*%3MR=0z)YW;K6q>plt6OP!bKnhyus2S=!ILt)->zn-N}q+ zGe8?u0Syen(?A(O@=4I~f4jK7GAmuT%f$-Oix-9rsQwGX^R^x=-(%crz4R;MJ}y>l zKeUvUQop1B#KpJUwuV`6zW6EkX(G#{saf9Gt9M%9;sk*8foPYtGYPQrszc3jFH3UMy z10i6WSr7in#T`kBoH?VJ3qz?W<$=Ls>$@?}akN)(zrWgu+foz7K zr7WgvqXtKoTvk)m*p#MLhg=lWtlPn;D^W`$o82DiDtf~%)*$h2M{{gIrKa7a*sRZy zDG)|DRo2SmF4bF=0*57HW@x?OXh($aAp86WNS>d^rEmD#3i}jf8Y{vot`u=ya!Z*m zqGR-Y;?8o;4Gm{NIg72#eN18d4#n06$She3h!$c74M;9o4H!i*z<>zC1{Me#Vopr8 zD`Nl%sRKoF96}=i6B<P!NEHc7Pi&&J+lLcyZ*v6z(Og_pC1| zn_pPJf?R%h>EGjRsB$~+=_8|?4Q^CF@aBn{ofE9myQg#h@zwPG;5)qMZmrK8MrO6PEVU!6Gi5$LgB2Rt3I@0tB_!$zU!vV!e75p*n_mf zA-hbeyynY%Ja&JW19r>Z$;6oIkHKyM3xI%rz*Y+|VeIen~i2W>60 z+|K$D;&i}^PqD0R9ekZ)o=aI23sNg7k%8u=)n$td8nex$#mtBmip^fLFd%GI1Qd$QM2i&~%O*oUNC zMoth~rXLBn+r^l2_O5lvR3v^)D6cbK3K;FGL60CHIORyetslF$KK4lcPCc3$AYypU zurMHH7)nqE2r)6EWEg~-NE~)RX%I#hJa$D+BOuwEbifLD8Nee#mi~TETclLyNabIlb4}{ZBp$rtyd_QztL)1 zX-XAp#QmX||IonEkbV!^+vaPJoH`TY;be}~${`AP#%0(N(K1ef&Tm}Oi>!8)Ojbqu z)j1SS+v8e0W>i;&))tO1IHH5PmRzT$; zN^!BzRE-24V+F$N@=Pq@O0S92Qq;TOOOg&{PoG()Qpp%4n?2A=u0^Vt@%T_tJogl1 zJkv`YB@X8uxOC+TFXmGa`|_lSzpgEZRm2NOy-Lc^$#DK?Ch^>Ny~bN+eXiclkrJc6 z5c>QoL#Cu$|7wne{r&SWaZAC$1gXN>fSC@XD!DcwcHl^?U^t;Z8i#nH3s4*&fbd~= z0}3F5AoK!?1Eol;7FZ9%BcK4RfC5(mutI}ich7huk}mvs;=G+Ie^%6AmF+7=^_lG} zGq~ialo;-l{WQ1!;L#5^xcQj-Kt?&Md$;N-P^o&s0cyFiqhWpNO-T z@72qM0(>=PT9NU@zwl49tL`UDj%F~VXY=uL%^JyFY2%dra0(CRokd8j$Y92u+< zNF;*1^H;~Njp6JVn^X?lrRe7BHNWx7rR7DGLy3gyt2(Xrue6Hz>?*dl`?_8H%P+5I HqM!T+FLlTe literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/js/jquery.fineuploader-3.2.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/js/jquery.fineuploader-3.2.js new file mode 100644 index 0000000..177bf12 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/js/jquery.fineuploader-3.2.js @@ -0,0 +1,3245 @@ +/** + * http://github.com/Valums-File-Uploader/file-uploader + * + * Multiple file upload component with progress-bar, drag-and-drop, support for all modern browsers. + * + * Original version: 1.0 © 2010 Andrew Valums ( andrew(at)valums.com ) + * Current Maintainer (2.0+): © 2012, Ray Nicholus ( fineuploader(at)garstasio.com ) + * + * Licensed under MIT license, GNU GPL 2 or later, GNU LGPL 2 or later, see license.txt. + */ +/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest*/ +var qq = function (element) { + "use strict"; + + return { + hide: function () { + element.style.display = 'none'; + return this; + }, + + /** Returns the function which detaches attached event */ + attach: function (type, fn) { + if (element.addEventListener) { + element.addEventListener(type, fn, false); + } else if (element.attachEvent) { + element.attachEvent('on' + type, fn); + } + return function () { + qq(element).detach(type, fn); + }; + }, + + detach: function (type, fn) { + if (element.removeEventListener) { + element.removeEventListener(type, fn, false); + } else if (element.attachEvent) { + element.detachEvent('on' + type, fn); + } + return this; + }, + + contains: function (descendant) { + // compareposition returns false in this case + if (element === descendant) { + return true; + } + + if (element.contains) { + return element.contains(descendant); + } else { + /*jslint bitwise: true*/ + return !!(descendant.compareDocumentPosition(element) & 8); + } + }, + + /** + * Insert this element before elementB. + */ + insertBefore: function (elementB) { + elementB.parentNode.insertBefore(element, elementB); + return this; + }, + + remove: function () { + element.parentNode.removeChild(element); + return this; + }, + + /** + * Sets styles for an element. + * Fixes opacity in IE6-8. + */ + css: function (styles) { + if (styles.opacity !== null) { + if (typeof element.style.opacity !== 'string' && typeof(element.filters) !== 'undefined') { + styles.filter = 'alpha(opacity=' + Math.round(100 * styles.opacity) + ')'; + } + } + qq.extend(element.style, styles); + + return this; + }, + + hasClass: function (name) { + var re = new RegExp('(^| )' + name + '( |$)'); + return re.test(element.className); + }, + + addClass: function (name) { + if (!qq(element).hasClass(name)) { + element.className += ' ' + name; + } + return this; + }, + + removeClass: function (name) { + var re = new RegExp('(^| )' + name + '( |$)'); + element.className = element.className.replace(re, ' ').replace(/^\s+|\s+$/g, ""); + return this; + }, + + getByClass: function (className) { + var candidates, + result = []; + + if (element.querySelectorAll) { + return element.querySelectorAll('.' + className); + } + + candidates = element.getElementsByTagName("*"); + + qq.each(candidates, function (idx, val) { + if (qq(val).hasClass(className)) { + result.push(val); + } + }); + return result; + }, + + children: function () { + var children = [], + child = element.firstChild; + + while (child) { + if (child.nodeType === 1) { + children.push(child); + } + child = child.nextSibling; + } + + return children; + }, + + setText: function (text) { + element.innerText = text; + element.textContent = text; + return this; + }, + + clearText: function () { + return qq(element).setText(""); + } + }; +}; + +qq.log = function (message, level) { + "use strict"; + + if (window.console) { + if (!level || level === 'info') { + window.console.log(message); + } + else { + if (window.console[level]) { + window.console[level](message); + } + else { + window.console.log('<' + level + '> ' + message); + } + } + } +}; + +qq.isObject = function (variable) { + "use strict"; + return variable !== null && variable && typeof(variable) === "object" && variable.constructor === Object; +}; + +qq.isFunction = function (variable) { + "use strict"; + return typeof(variable) === "function"; +}; + +qq.isFileOrInput = function (maybeFileOrInput) { + "use strict"; + if (window.File && maybeFileOrInput instanceof File) { + return true; + } + else if (window.HTMLInputElement) { + if (maybeFileOrInput instanceof HTMLInputElement) { + if (maybeFileOrInput.type && maybeFileOrInput.type.toLowerCase() === 'file') { + return true; + } + } + } + else if (maybeFileOrInput.tagName) { + if (maybeFileOrInput.tagName.toLowerCase() === 'input') { + if (maybeFileOrInput.type && maybeFileOrInput.type.toLowerCase() === 'file') { + return true; + } + } + } + + return false; +}; + +qq.isXhrUploadSupported = function () { + "use strict"; + var input = document.createElement('input'); + input.type = 'file'; + + return ( + input.multiple !== undefined && + typeof File !== "undefined" && + typeof FormData !== "undefined" && + typeof (new XMLHttpRequest()).upload !== "undefined" ); +}; + +qq.isFolderDropSupported = function (dataTransfer) { + "use strict"; + return (dataTransfer.items && dataTransfer.items[0].webkitGetAsEntry); +}; + +qq.isFileChunkingSupported = function () { + "use strict"; + return !qq.android() && //android's impl of Blob.slice is broken + qq.isXhrUploadSupported() && + (File.prototype.slice || File.prototype.webkitSlice || File.prototype.mozSlice); +}; + +qq.extend = function (first, second, extendNested) { + "use strict"; + qq.each(second, function (prop, val) { + if (extendNested && qq.isObject(val)) { + if (first[prop] === undefined) { + first[prop] = {}; + } + qq.extend(first[prop], val, true); + } + else { + first[prop] = val; + } + }); +}; + +/** + * Searches for a given element in the array, returns -1 if it is not present. + * @param {Number} [from] The index at which to begin the search + */ +qq.indexOf = function (arr, elt, from) { + "use strict"; + + if (arr.indexOf) { + return arr.indexOf(elt, from); + } + + from = from || 0; + var len = arr.length; + + if (from < 0) { + from += len; + } + + for (; from < len; from += 1) { + if (arr.hasOwnProperty(from) && arr[from] === elt) { + return from; + } + } + return -1; +}; + +//this is a version 4 UUID +qq.getUniqueId = function () { + "use strict"; + + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + /*jslint eqeq: true, bitwise: true*/ + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +}; + +// +// Browsers and platforms detection + +qq.ie = function () { + "use strict"; + return navigator.userAgent.indexOf('MSIE') !== -1; +}; +qq.ie10 = function () { + "use strict"; + return navigator.userAgent.indexOf('MSIE 10') !== -1; +}; +qq.safari = function () { + "use strict"; + return navigator.vendor !== undefined && navigator.vendor.indexOf("Apple") !== -1; +}; +qq.chrome = function () { + "use strict"; + return navigator.vendor !== undefined && navigator.vendor.indexOf('Google') !== -1; +}; +qq.firefox = function () { + "use strict"; + return (navigator.userAgent.indexOf('Mozilla') !== -1 && navigator.vendor !== undefined && navigator.vendor === ''); +}; +qq.windows = function () { + "use strict"; + return navigator.platform === "Win32"; +}; +qq.android = function () { + "use strict"; + return navigator.userAgent.toLowerCase().indexOf('android') !== -1; +}; + +// +// Events + +qq.preventDefault = function (e) { + "use strict"; + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } +}; + +/** + * Creates and returns element from html string + * Uses innerHTML to create an element + */ +qq.toElement = (function () { + "use strict"; + var div = document.createElement('div'); + return function (html) { + div.innerHTML = html; + var element = div.firstChild; + div.removeChild(element); + return element; + }; +}()); + +//key and value are passed to callback for each item in the object or array +qq.each = function (obj, callback) { + "use strict"; + var key, retVal; + if (obj) { + for (key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + retVal = callback(key, obj[key]); + if (retVal === false) { + break; + } + } + } + } +}; + +/** + * obj2url() takes a json-object as argument and generates + * a querystring. pretty much like jQuery.param() + * + * how to use: + * + * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');` + * + * will result in: + * + * `http://any.url/upload?otherParam=value&a=b&c=d` + * + * @param Object JSON-Object + * @param String current querystring-part + * @return String encoded querystring + */ +qq.obj2url = function (obj, temp, prefixDone) { + "use strict"; + /*jshint laxbreak: true*/ + var i, len, + uristrings = [], + prefix = '&', + add = function (nextObj, i) { + var nextTemp = temp + ? (/\[\]$/.test(temp)) // prevent double-encoding + ? temp + : temp + '[' + i + ']' + : i; + if ((nextTemp !== 'undefined') && (i !== 'undefined')) { + uristrings.push( + (typeof nextObj === 'object') + ? qq.obj2url(nextObj, nextTemp, true) + : (Object.prototype.toString.call(nextObj) === '[object Function]') + ? encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj()) + : encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj) + ); + } + }; + + if (!prefixDone && temp) { + prefix = (/\?/.test(temp)) ? (/\?$/.test(temp)) ? '' : '&' : '?'; + uristrings.push(temp); + uristrings.push(qq.obj2url(obj)); + } else if ((Object.prototype.toString.call(obj) === '[object Array]') && (typeof obj !== 'undefined')) { + // we wont use a for-in-loop on an array (performance) + for (i = -1, len = obj.length; i < len; i += 1) { + add(obj[i], i); + } + } else if ((typeof obj !== 'undefined') && (obj !== null) && (typeof obj === "object")) { + // for anything else but a scalar, we will use for-in-loop + for (i in obj) { + if (obj.hasOwnProperty(i)) { + add(obj[i], i); + } + } + } else { + uristrings.push(encodeURIComponent(temp) + '=' + encodeURIComponent(obj)); + } + + if (temp) { + return uristrings.join(prefix); + } else { + return uristrings.join(prefix) + .replace(/^&/, '') + .replace(/%20/g, '+'); + } +}; + +qq.obj2FormData = function (obj, formData, arrayKeyName) { + "use strict"; + if (!formData) { + formData = new FormData(); + } + + qq.each(obj, function (key, val) { + key = arrayKeyName ? arrayKeyName + '[' + key + ']' : key; + + if (qq.isObject(val)) { + qq.obj2FormData(val, formData, key); + } + else if (qq.isFunction(val)) { + formData.append(encodeURIComponent(key), encodeURIComponent(val())); + } + else { + formData.append(encodeURIComponent(key), encodeURIComponent(val)); + } + }); + + return formData; +}; + +qq.obj2Inputs = function (obj, form) { + "use strict"; + var input; + + if (!form) { + form = document.createElement('form'); + } + + qq.obj2FormData(obj, { + append: function (key, val) { + input = document.createElement('input'); + input.setAttribute('name', key); + input.setAttribute('value', val); + form.appendChild(input); + } + }); + + return form; +}; + +qq.setCookie = function (name, value, days) { + var date = new Date(), + expires = ""; + + if (days) { + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = "; expires=" + date.toGMTString(); + } + + document.cookie = name + "=" + value + expires + "; path=/"; +}; + +qq.getCookie = function (name) { + var nameEQ = name + "=", + ca = document.cookie.split(';'), + c; + + for (var i = 0; i < ca.length; i++) { + c = ca[i]; + while (c.charAt(0) == ' ') { + c = c.substring(1, c.length); + } + if (c.indexOf(nameEQ) === 0) { + return c.substring(nameEQ.length, c.length); + } + } +}; + +qq.getCookieNames = function (regexp) { + var cookies = document.cookie.split(';'), + cookieNames = []; + + qq.each(cookies, function (idx, cookie) { + cookie = cookie.trim(); + + var equalsIdx = cookie.indexOf("="); + + if (cookie.match(regexp)) { + cookieNames.push(cookie.substr(0, equalsIdx)); + } + }); + + return cookieNames; +}; + +qq.deleteCookie = function (name) { + qq.setCookie(name, "", -1); +}; + +qq.areCookiesEnabled = function () { + var randNum = Math.random() * 100000, + name = "qqCookieTest:" + randNum; + qq.setCookie(name, 1); + + if (qq.getCookie(name)) { + qq.deleteCookie(name); + return true; + } + return false; +}; + +/** + * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not + * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js. + */ +qq.parseJson = function (json) { + /*jshint evil: true*/ + if (typeof JSON.parse === "function") { + return JSON.parse(json); + } else { + return eval("(" + json + ")"); + } +}; + +/** + * A generic module which supports object disposing in dispose() method. + * */ +qq.DisposeSupport = function () { + "use strict"; + var disposers = []; + + return { + /** Run all registered disposers */ + dispose: function () { + var disposer; + do { + disposer = disposers.shift(); + if (disposer) { + disposer(); + } + } + while (disposer); + }, + + /** Attach event handler and register de-attacher as a disposer */ + attach: function () { + var args = arguments; + /*jslint undef:true*/ + this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1))); + }, + + /** Add disposer to the collection */ + addDisposer: function (disposeFunction) { + disposers.push(disposeFunction); + } + }; +}; +qq.UploadButton = function (o) { + this._options = { + element: null, + // if set to true adds multiple attribute to file input + multiple: false, + acceptFiles: null, + // name attribute of file input + name: 'file', + onChange: function (input) { + }, + hoverClass: 'qq-upload-button-hover', + focusClass: 'qq-upload-button-focus' + }; + + qq.extend(this._options, o); + this._disposeSupport = new qq.DisposeSupport(); + + this._element = this._options.element; + + // make button suitable container for input + qq(this._element).css({ + position: 'relative', + overflow: 'hidden', + // Make sure browse button is in the right side + // in Internet Explorer + direction: 'ltr' + }); + + this._input = this._createInput(); +}; + +qq.UploadButton.prototype = { + /* returns file input element */ + getInput: function () { + return this._input; + }, + /* cleans/recreates the file input */ + reset: function () { + if (this._input.parentNode) { + qq(this._input).remove(); + } + + qq(this._element).removeClass(this._options.focusClass); + this._input = this._createInput(); + }, + _createInput: function () { + var input = document.createElement("input"); + + if (this._options.multiple) { + input.setAttribute("multiple", "multiple"); + } + + if (this._options.acceptFiles) input.setAttribute("accept", this._options.acceptFiles); + + input.setAttribute("type", "file"); + input.setAttribute("name", this._options.name); + + qq(input).css({ + position: 'absolute', + // in Opera only 'browse' button + // is clickable and it is located at + // the right side of the input + right: 0, + top: 0, + fontFamily: 'Arial', + // 4 persons reported this, the max values that worked for them were 243, 236, 236, 118 + fontSize: '118px', + margin: 0, + padding: 0, + cursor: 'pointer', + opacity: 0 + }); + + this._element.appendChild(input); + + var self = this; + this._disposeSupport.attach(input, 'change', function () { + self._options.onChange(input); + }); + + this._disposeSupport.attach(input, 'mouseover', function () { + qq(self._element).addClass(self._options.hoverClass); + }); + this._disposeSupport.attach(input, 'mouseout', function () { + qq(self._element).removeClass(self._options.hoverClass); + }); + this._disposeSupport.attach(input, 'focus', function () { + qq(self._element).addClass(self._options.focusClass); + }); + this._disposeSupport.attach(input, 'blur', function () { + qq(self._element).removeClass(self._options.focusClass); + }); + + // IE and Opera, unfortunately have 2 tab stops on file input + // which is unacceptable in our case, disable keyboard access + if (window.attachEvent) { + // it is IE or Opera + input.setAttribute('tabIndex', "-1"); + } + + return input; + } +}; +/** + * Class for uploading files, uploading itself is handled by child classes + */ +/*globals qq*/ +qq.UploadHandler = function (o) { + "use strict"; + + var queue = [], + options, log, dequeue, handlerImpl; + + // Default options, can be overridden by the user + options = { + debug: false, + forceMultipart: true, + paramsInBody: false, + paramsStore: {}, + endpointStore: {}, + maxConnections: 3, // maximum number of concurrent uploads + uuidParamName: 'qquuid', + totalFileSizeParamName: 'qqtotalfilesize', + chunking: { + enabled: false, + partSize: 2000000, //bytes + paramNames: { + partIndex: 'qqpartindex', + partByteOffset: 'qqpartbyteoffset', + chunkSize: 'qqchunksize', + totalParts: 'qqtotalparts', + filename: 'qqfilename' + } + }, + resume: { + enabled: false, + id: null, + cookiesExpireIn: 7, //days + paramNames: { + resuming: "qqresume" + } + }, + log: function (str, level) { + }, + onProgress: function (id, fileName, loaded, total) { + }, + onComplete: function (id, fileName, response, xhr) { + }, + onCancel: function (id, fileName) { + }, + onUpload: function (id, fileName) { + }, + onUploadChunk: function (id, fileName, chunkData) { + }, + onAutoRetry: function (id, fileName, response, xhr) { + }, + onResume: function (id, fileName, chunkData) { + } + + }; + qq.extend(options, o); + + log = options.log; + + /** + * Removes element from queue, starts upload of next + */ + dequeue = function (id) { + var i = qq.indexOf(queue, id), + max = options.maxConnections, + nextId; + + queue.splice(i, 1); + + if (queue.length >= max && i < max) { + nextId = queue[max - 1]; + handlerImpl.upload(nextId); + } + }; + + if (qq.isXhrUploadSupported()) { + handlerImpl = new qq.UploadHandlerXhr(options, dequeue, log); + } + else { + handlerImpl = new qq.UploadHandlerForm(options, dequeue, log); + } + + + return { + /** + * Adds file or file input to the queue + * @returns id + **/ + add: function (file) { + return handlerImpl.add(file); + }, + /** + * Sends the file identified by id + */ + upload: function (id) { + var len = queue.push(id); + + // if too many active uploads, wait... + if (len <= options.maxConnections) { + return handlerImpl.upload(id); + } + }, + retry: function (id) { + var i = qq.indexOf(queue, id); + if (i >= 0) { + return handlerImpl.upload(id, true); + } + else { + return this.upload(id); + } + }, + /** + * Cancels file upload by id + */ + cancel: function (id) { + log('Cancelling ' + id); + options.paramsStore.remove(id); + handlerImpl.cancel(id); + dequeue(id); + }, + /** + * Cancels all uploads + */ + cancelAll: function () { + qq.each(queue, function (idx, fileId) { + this.cancel(fileId); + }); + + queue = []; + }, + /** + * Returns name of the file identified by id + */ + getName: function (id) { + return handlerImpl.getName(id); + }, + /** + * Returns size of the file identified by id + */ + getSize: function (id) { + if (handlerImpl.getSize) { + return handlerImpl.getSize(id); + } + }, + getFile: function (id) { + if (handlerImpl.getFile) { + return handlerImpl.getFile(id); + } + }, + /** + * Returns id of files being uploaded or + * waiting for their turn + */ + getQueue: function () { + return queue; + }, + reset: function () { + log('Resetting upload handler'); + queue = []; + handlerImpl.reset(); + }, + getUuid: function (id) { + return handlerImpl.getUuid(id); + }, + /** + * Determine if the file exists. + */ + isValid: function (id) { + return handlerImpl.isValid(id); + }, + getResumableFilesData: function () { + if (handlerImpl.getResumableFilesData) { + return handlerImpl.getResumableFilesData(); + } + return []; + } + }; +}; +/*globals qq, document, setTimeout*/ +/*jslint white: true*/ +qq.UploadHandlerForm = function (o, uploadCompleteCallback, logCallback) { + "use strict"; + + var options = o, + inputs = [], + uuids = [], + detachLoadEvents = {}, + uploadComplete = uploadCompleteCallback, + log = logCallback, + api; + + function attachLoadEvent(iframe, callback) { + /*jslint eqeq: true*/ + + detachLoadEvents[iframe.id] = qq(iframe).attach('load', function () { + log('Received response for ' + iframe.id); + + // when we remove iframe from dom + // the request stops, but in IE load + // event fires + if (!iframe.parentNode) { + return; + } + + try { + // fixing Opera 10.53 + if (iframe.contentDocument && + iframe.contentDocument.body && + iframe.contentDocument.body.innerHTML == "false") { + // In Opera event is fired second time + // when body.innerHTML changed from false + // to server response approx. after 1 sec + // when we upload file with iframe + return; + } + } + catch (error) { + //IE may throw an "access is denied" error when attempting to access contentDocument on the iframe in some cases + log('Error when attempting to access iframe during handling of upload response (' + error + ")", 'error'); + } + + callback(); + }); + } + + /** + * Returns json object received by iframe from server. + */ + function getIframeContentJson(iframe) { + /*jshint evil: true*/ + + var response; + + //IE may throw an "access is denied" error when attempting to access contentDocument on the iframe in some cases + try { + // iframe.contentWindow.document - for IE<7 + var doc = iframe.contentDocument || iframe.contentWindow.document, + innerHTML = doc.body.innerHTML; + + log("converting iframe's innerHTML to JSON"); + log("innerHTML = " + innerHTML); + //plain text response may be wrapped in
     tag
    +            if (innerHTML && innerHTML.match(/^
    ');
    +        // src="javascript:false;" removes ie6 prompt on https
    +
    +        iframe.setAttribute('id', id);
    +
    +        iframe.style.display = 'none';
    +        document.body.appendChild(iframe);
    +
    +        return iframe;
    +    }
    +
    +    /**
    +     * Creates form, that will be submitted to iframe
    +     */
    +    function createForm(id, iframe) {
    +        var params = options.paramsStore.getParams(id),
    +            protocol = options.demoMode ? "GET" : "POST",
    +            form = qq.toElement('
    '), + endpoint = options.endpointStore.getEndpoint(id), + url = endpoint; + + params[options.uuidParamName] = uuids[id]; + + if (!options.paramsInBody) { + url = qq.obj2url(params, endpoint); + } + else { + qq.obj2Inputs(params, form); + } + + form.setAttribute('action', url); + form.setAttribute('target', iframe.name); + form.style.display = 'none'; + document.body.appendChild(form); + + return form; + } + + + api = { + add: function (fileInput) { + fileInput.setAttribute('name', options.inputName); + + var id = inputs.push(fileInput) - 1; + uuids[id] = qq.getUniqueId(); + + // remove file input from DOM + if (fileInput.parentNode) { + qq(fileInput).remove(); + } + + return id; + }, + getName: function (id) { + /*jslint regexp: true*/ + + // get input value and remove path to normalize + return inputs[id].value.replace(/.*(\/|\\)/, ""); + }, + isValid: function (id) { + return inputs[id] !== undefined; + }, + reset: function () { + qq.UploadHandler.prototype.reset.apply(this, arguments); + inputs = []; + uuids = []; + detachLoadEvents = {}; + }, + getUuid: function (id) { + return uuids[id]; + }, + cancel: function (id) { + options.onCancel(id, this.getName(id)); + + delete inputs[id]; + delete uuids[id]; + delete detachLoadEvents[id]; + + var iframe = document.getElementById(id); + if (iframe) { + // to cancel request set src to something else + // we use src="javascript:false;" because it doesn't + // trigger ie6 prompt on https + iframe.setAttribute('src', 'java' + String.fromCharCode(115) + 'cript:false;'); //deal with "JSLint: javascript URL" warning, which apparently cannot be turned off + + qq(iframe).remove(); + } + }, + upload: function (id) { + var input = inputs[id], + fileName = api.getName(id), + iframe = createIframe(id), + form = createForm(id, iframe); + + if (!input) { + throw new Error('file with passed id was not added, or already uploaded or cancelled'); + } + + options.onUpload(id, this.getName(id)); + + form.appendChild(input); + + attachLoadEvent(iframe, function () { + log('iframe loaded'); + + var response = getIframeContentJson(iframe); + + // timeout added to fix busy state in FF3.6 + setTimeout(function () { + detachLoadEvents[id](); + delete detachLoadEvents[id]; + qq(iframe).remove(); + }, 1); + + if (!response.success) { + if (options.onAutoRetry(id, fileName, response)) { + return; + } + } + options.onComplete(id, fileName, response); + uploadComplete(id); + }); + + log('Sending upload request for ' + id); + form.submit(); + qq(form).remove(); + + return id; + } + }; + + return api; +}; +/*globals qq, File, XMLHttpRequest, FormData*/ +qq.UploadHandlerXhr = function (o, uploadCompleteCallback, logCallback) { + "use strict"; + + var options = o, + uploadComplete = uploadCompleteCallback, + log = logCallback, + fileState = [], + cookieItemDelimiter = "|", + chunkFiles = options.chunking.enabled && qq.isFileChunkingSupported(), + resumeEnabled = options.resume.enabled && chunkFiles && qq.areCookiesEnabled(), + resumeId = getResumeId(), + multipart = options.forceMultipart || options.paramsInBody, + api; + + + function addChunkingSpecificParams(id, params, chunkData) { + var size = api.getSize(id), + name = api.getName(id); + + params[options.chunking.paramNames.partIndex] = chunkData.part; + params[options.chunking.paramNames.partByteOffset] = chunkData.start; + params[options.chunking.paramNames.chunkSize] = chunkData.end - chunkData.start; + params[options.chunking.paramNames.totalParts] = chunkData.count; + params[options.totalFileSizeParamName] = size; + + + /** + * When a Blob is sent in a multipart request, the filename value in the content-disposition header is either "blob" + * or an empty string. So, we will need to include the actual file name as a param in this case. + */ + if (multipart) { + params[options.chunking.paramNames.filename] = name; + } + } + + function addResumeSpecificParams(params) { + params[options.resume.paramNames.resuming] = true; + } + + function getChunk(file, startByte, endByte) { + if (file.slice) { + return file.slice(startByte, endByte); + } + else if (file.mozSlice) { + return file.mozSlice(startByte, endByte); + } + else if (file.webkitSlice) { + return file.webkitSlice(startByte, endByte); + } + } + + function getChunkData(id, chunkIndex) { + var chunkSize = options.chunking.partSize, + fileSize = api.getSize(id), + file = fileState[id].file, + startBytes = chunkSize * chunkIndex, + endBytes = startBytes + chunkSize >= fileSize ? fileSize : startBytes + chunkSize, + totalChunks = getTotalChunks(id); + + return { + part: chunkIndex, + start: startBytes, + end: endBytes, + count: totalChunks, + blob: getChunk(file, startBytes, endBytes) + }; + } + + function getTotalChunks(id) { + var fileSize = api.getSize(id), + chunkSize = options.chunking.partSize; + + return Math.ceil(fileSize / chunkSize); + } + + function createXhr(id) { + fileState[id].xhr = new XMLHttpRequest(); + return fileState[id].xhr; + } + + function setParamsAndGetEntityToSend(params, xhr, fileOrBlob, id) { + var formData = new FormData(), + protocol = options.demoMode ? "GET" : "POST", + endpoint = options.endpointStore.getEndpoint(id), + url = endpoint, + name = api.getName(id), + size = api.getSize(id); + + params[options.uuidParamName] = fileState[id].uuid; + + if (multipart) { + params[options.totalFileSizeParamName] = size; + } + + //build query string + if (!options.paramsInBody) { + params[options.inputName] = name; + url = qq.obj2url(params, endpoint); + } + + xhr.open(protocol, url, true); + if (multipart) { + if (options.paramsInBody) { + qq.obj2FormData(params, formData); + } + + formData.append(options.inputName, fileOrBlob); + return formData; + } + + return fileOrBlob; + } + + function setHeaders(id, xhr) { + var extraHeaders = options.customHeaders, + name = api.getName(id), + file = fileState[id].file; + + xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + xhr.setRequestHeader("Cache-Control", "no-cache"); + + if (!multipart) { + xhr.setRequestHeader("Content-Type", "application/octet-stream"); + //NOTE: return mime type in xhr works on chrome 16.0.9 firefox 11.0a2 + xhr.setRequestHeader("X-Mime-Type", file.type); + } + + qq.each(extraHeaders, function (name, val) { + xhr.setRequestHeader(name, val); + }); + } + + function handleCompletedFile(id, response, xhr) { + var name = api.getName(id), + size = api.getSize(id); + + fileState[id].attemptingResume = false; + + options.onProgress(id, name, size, size); + + options.onComplete(id, name, response, xhr); + delete fileState[id].xhr; + uploadComplete(id); + } + + function uploadNextChunk(id) { + var chunkData = getChunkData(id, fileState[id].remainingChunkIdxs[0]), + xhr = createXhr(id), + size = api.getSize(id), + name = api.getName(id), + toSend, params; + + if (fileState[id].loaded === undefined) { + fileState[id].loaded = 0; + } + + persistChunkData(id, chunkData); + + xhr.onreadystatechange = getReadyStateChangeHandler(id, xhr); + + xhr.upload.onprogress = function (e) { + if (e.lengthComputable) { + if (fileState[id].loaded < size) { + var totalLoaded = e.loaded + fileState[id].loaded; + options.onProgress(id, name, totalLoaded, size); + } + } + }; + + options.onUploadChunk(id, name, getChunkDataForCallback(chunkData)); + + params = options.paramsStore.getParams(id); + addChunkingSpecificParams(id, params, chunkData); + + if (fileState[id].attemptingResume) { + addResumeSpecificParams(params); + } + + toSend = setParamsAndGetEntityToSend(params, xhr, chunkData.blob, id); + setHeaders(id, xhr); + + log('Sending chunked upload request for ' + id + ": bytes " + (chunkData.start + 1) + "-" + chunkData.end + " of " + size); + xhr.send(toSend); + } + + + function handleSuccessfullyCompletedChunk(id, response, xhr) { + var chunkIdx = fileState[id].remainingChunkIdxs.shift(), + chunkData = getChunkData(id, chunkIdx); + + fileState[id].attemptingResume = false; + fileState[id].loaded += chunkData.end - chunkData.start; + + if (fileState[id].remainingChunkIdxs.length > 0) { + uploadNextChunk(id); + } + else { + deletePersistedChunkData(id); + handleCompletedFile(id, response, xhr); + } + } + + function isErrorResponse(xhr, response) { + return xhr.status !== 200 || !response.success || response.reset; + } + + function parseResponse(xhr) { + var response; + + try { + response = qq.parseJson(xhr.responseText); + } + catch (error) { + log('Error when attempting to parse xhr response text (' + error + ')', 'error'); + response = {}; + } + + return response; + } + + function handleResetResponse(id) { + log('Server has ordered chunking effort to be restarted on next attempt for file ID ' + id, 'error'); + + if (resumeEnabled) { + deletePersistedChunkData(id); + } + fileState[id].remainingChunkIdxs = []; + delete fileState[id].loaded; + } + + function handleResetResponseOnResumeAttempt(id) { + fileState[id].attemptingResume = false; + log("Server has declared that it cannot handle resume for file ID " + id + " - starting from the first chunk", 'error'); + api.upload(id, true); + } + + function handleNonResetErrorResponse(id, response, xhr) { + var name = api.getName(id); + + if (options.onAutoRetry(id, name, response, xhr)) { + return; + } + else { + handleCompletedFile(id, response, xhr); + } + } + + function onComplete(id, xhr) { + var response; + + // the request was aborted/cancelled + if (!fileState[id]) { + return; + } + + log("xhr - server response received for " + id); + log("responseText = " + xhr.responseText); + response = parseResponse(xhr); + + if (isErrorResponse(xhr, response)) { + if (response.reset) { + handleResetResponse(id); + } + + if (fileState[id].attemptingResume && response.reset) { + handleResetResponseOnResumeAttempt(id); + } + else { + handleNonResetErrorResponse(id, response, xhr); + } + } + else if (chunkFiles) { + handleSuccessfullyCompletedChunk(id, response, xhr); + } + else { + handleCompletedFile(id, response, xhr); + } + } + + function getChunkDataForCallback(chunkData) { + return { + partIndex: chunkData.part, + startByte: chunkData.start + 1, + endByte: chunkData.end, + totalParts: chunkData.count + }; + } + + function getReadyStateChangeHandler(id, xhr) { + return function () { + if (xhr.readyState === 4) { + onComplete(id, xhr); + } + }; + } + + function persistChunkData(id, chunkData) { + var fileUuid = api.getUuid(id), + cookieName = getChunkDataCookieName(id), + cookieValue = fileUuid + cookieItemDelimiter + chunkData.part, + cookieExpDays = options.resume.cookiesExpireIn; + + qq.setCookie(cookieName, cookieValue, cookieExpDays); + } + + function deletePersistedChunkData(id) { + var cookieName = getChunkDataCookieName(id); + + qq.deleteCookie(cookieName); + } + + function getPersistedChunkData(id) { + var chunkCookieValue = qq.getCookie(getChunkDataCookieName(id)), + delimiterIndex, uuid, partIndex; + + if (chunkCookieValue) { + delimiterIndex = chunkCookieValue.indexOf(cookieItemDelimiter); + uuid = chunkCookieValue.substr(0, delimiterIndex); + partIndex = parseInt(chunkCookieValue.substr(delimiterIndex + 1, chunkCookieValue.length - delimiterIndex), 10); + + return { + uuid: uuid, + part: partIndex + }; + } + } + + function getChunkDataCookieName(id) { + var filename = api.getName(id), + fileSize = api.getSize(id), + maxChunkSize = options.chunking.partSize, + cookieName; + + cookieName = "qqfilechunk" + cookieItemDelimiter + encodeURIComponent(filename) + cookieItemDelimiter + fileSize + cookieItemDelimiter + maxChunkSize; + + if (resumeId !== undefined) { + cookieName += cookieItemDelimiter + resumeId; + } + + return cookieName; + } + + function getResumeId() { + if (options.resume.id !== null && + options.resume.id !== undefined && !qq.isFunction(options.resume.id) && !qq.isObject(options.resume.id)) { + + return options.resume.id; + } + } + + function handleFileChunkingUpload(id, retry) { + var name = api.getName(id), + firstChunkIndex = 0, + persistedChunkInfoForResume, firstChunkDataForResume, currentChunkIndex; + + if (!fileState[id].remainingChunkIdxs || fileState[id].remainingChunkIdxs.length === 0) { + fileState[id].remainingChunkIdxs = []; + + if (resumeEnabled && !retry) { + persistedChunkInfoForResume = getPersistedChunkData(id); + if (persistedChunkInfoForResume) { + firstChunkDataForResume = getChunkData(id, persistedChunkInfoForResume.part); + if (options.onResume(id, name, getChunkDataForCallback(firstChunkDataForResume)) !== false) { + firstChunkIndex = persistedChunkInfoForResume.part; + fileState[id].uuid = persistedChunkInfoForResume.uuid; + fileState[id].loaded = firstChunkDataForResume.start; + fileState[id].attemptingResume = true; + log('Resuming ' + name + " at partition index " + firstChunkIndex); + } + } + } + + for (currentChunkIndex = getTotalChunks(id) - 1; currentChunkIndex >= firstChunkIndex; currentChunkIndex -= 1) { + fileState[id].remainingChunkIdxs.unshift(currentChunkIndex); + } + } + + uploadNextChunk(id); + } + + function handleStandardFileUpload(id) { + var file = fileState[id].file, + name = api.getName(id), + xhr, params, toSend; + + fileState[id].loaded = 0; + + xhr = createXhr(id); + + xhr.upload.onprogress = function (e) { + if (e.lengthComputable) { + fileState[id].loaded = e.loaded; + options.onProgress(id, name, e.loaded, e.total); + } + }; + + xhr.onreadystatechange = getReadyStateChangeHandler(id, xhr); + + params = options.paramsStore.getParams(id); + toSend = setParamsAndGetEntityToSend(params, xhr, file, id); + setHeaders(id, xhr); + + log('Sending upload request for ' + id); + xhr.send(toSend); + } + + + api = { + /** + * Adds file to the queue + * Returns id to use with upload, cancel + **/ + add: function (file) { + if (!(file instanceof File)) { + throw new Error('Passed obj in not a File (in qq.UploadHandlerXhr)'); + } + + + var id = fileState.push({file: file}) - 1; + fileState[id].uuid = qq.getUniqueId(); + + return id; + }, + getName: function (id) { + var file = fileState[id].file; + // fix missing name in Safari 4 + //NOTE: fixed missing name firefox 11.0a2 file.fileName is actually undefined + return (file.fileName !== null && file.fileName !== undefined) ? file.fileName : file.name; + }, + getSize: function (id) { + /*jshint eqnull: true*/ + var file = fileState[id].file; + return file.fileSize != null ? file.fileSize : file.size; + }, + getFile: function (id) { + if (fileState[id]) { + return fileState[id].file; + } + }, + /** + * Returns uploaded bytes for file identified by id + */ + getLoaded: function (id) { + return fileState[id].loaded || 0; + }, + isValid: function (id) { + return fileState[id] !== undefined; + }, + reset: function () { + fileState = []; + }, + getUuid: function (id) { + return fileState[id].uuid; + }, + /** + * Sends the file identified by id to the server + */ + upload: function (id, retry) { + var name = this.getName(id); + + options.onUpload(id, name); + + if (chunkFiles) { + handleFileChunkingUpload(id, retry); + } + else { + handleStandardFileUpload(id); + } + }, + cancel: function (id) { + options.onCancel(id, this.getName(id)); + + if (fileState[id].xhr) { + fileState[id].xhr.abort(); + } + + if (resumeEnabled) { + deletePersistedChunkData(id); + } + + delete fileState[id]; + }, + getResumableFilesData: function () { + var matchingCookieNames = [], + resumableFilesData = []; + + if (chunkFiles && resumeEnabled) { + if (resumeId === undefined) { + matchingCookieNames = qq.getCookieNames(new RegExp("^qqfilechunk\\" + cookieItemDelimiter + ".+\\" + + cookieItemDelimiter + "\\d+\\" + cookieItemDelimiter + options.chunking.partSize + "=")); + } + else { + matchingCookieNames = qq.getCookieNames(new RegExp("^qqfilechunk\\" + cookieItemDelimiter + ".+\\" + + cookieItemDelimiter + "\\d+\\" + cookieItemDelimiter + options.chunking.partSize + "\\" + + cookieItemDelimiter + resumeId + "=")); + } + + qq.each(matchingCookieNames, function (idx, cookieName) { + var cookiesNameParts = cookieName.split(cookieItemDelimiter); + var cookieValueParts = qq.getCookie(cookieName).split(cookieItemDelimiter); + + resumableFilesData.push({ + name: decodeURIComponent(cookiesNameParts[1]), + size: cookiesNameParts[2], + uuid: cookieValueParts[0], + partIdx: cookieValueParts[1] + }); + }); + + return resumableFilesData; + } + return []; + } + }; + + return api; +}; +qq.FineUploaderBasic = function (o) { + var that = this; + this._options = { + debug: false, + button: null, + multiple: true, + maxConnections: 3, + disableCancelForFormUploads: false, + autoUpload: true, + request: { + endpoint: '/server/upload', + params: {}, + paramsInBody: false, + customHeaders: {}, + forceMultipart: true, + inputName: 'qqfile', + uuidName: 'qquuid', + totalFileSizeName: 'qqtotalfilesize' + }, + validation: { + allowedExtensions: [], + sizeLimit: 0, + minSizeLimit: 0, + stopOnFirstInvalidFile: true + }, + callbacks: { + onSubmit: function (id, fileName) { + }, + onComplete: function (id, fileName, responseJSON) { + }, + onCancel: function (id, fileName) { + }, + onUpload: function (id, fileName) { + }, + onUploadChunk: function (id, fileName, chunkData) { + }, + onResume: function (id, fileName, chunkData) { + }, + onProgress: function (id, fileName, loaded, total) { + }, + onError: function (id, fileName, reason) { + }, + onAutoRetry: function (id, fileName, attemptNumber) { + }, + onManualRetry: function (id, fileName) { + }, + onValidateBatch: function (fileData) { + }, + onValidate: function (fileData) { + } + }, + messages: { + typeError: "{file} has an invalid extension. Valid extension(s): {extensions}.", + sizeError: "{file} is too large, maximum file size is {sizeLimit}.", + minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.", + emptyError: "{file} is empty, please select files again without it.", + noFilesError: "No files to upload.", + onLeave: "The files are being uploaded, if you leave now the upload will be cancelled." + }, + retry: { + enableAuto: false, + maxAutoAttempts: 3, + autoAttemptDelay: 5, + preventRetryResponseProperty: 'preventRetry' + }, + classes: { + buttonHover: 'qq-upload-button-hover', + buttonFocus: 'qq-upload-button-focus' + }, + chunking: { + enabled: false, + partSize: 2000000, + paramNames: { + partIndex: 'qqpartindex', + partByteOffset: 'qqpartbyteoffset', + chunkSize: 'qqchunksize', + totalFileSize: 'qqtotalfilesize', + totalParts: 'qqtotalparts', + filename: 'qqfilename' + } + }, + resume: { + enabled: false, + id: null, + cookiesExpireIn: 7, //days + paramNames: { + resuming: "qqresume" + } + }, + formatFileName: function (fileName) { + if (fileName.length > 33) { + fileName = fileName.slice(0, 19) + '...' + fileName.slice(-14); + } + return fileName; + }, + text: { + sizeSymbols: ['kB', 'MB', 'GB', 'TB', 'PB', 'EB'] + } + }; + + qq.extend(this._options, o, true); + this._wrapCallbacks(); + this._disposeSupport = new qq.DisposeSupport(); + + // number of files being uploaded + this._filesInProgress = []; + + this._storedFileIds = []; + + this._autoRetries = []; + this._retryTimeouts = []; + this._preventRetries = []; + + this._paramsStore = this._createParamsStore(); + this._endpointStore = this._createEndpointStore(); + + this._handler = this._createUploadHandler(); + + if (this._options.button) { + this._button = this._createUploadButton(this._options.button); + } + + this._preventLeaveInProgress(); +}; + +qq.FineUploaderBasic.prototype = { + log: function (str, level) { + if (this._options.debug && (!level || level === 'info')) { + qq.log('[FineUploader] ' + str); + } + else if (level && level !== 'info') { + qq.log('[FineUploader] ' + str, level); + + } + }, + setParams: function (params, fileId) { + /*jshint eqeqeq: true, eqnull: true*/ + if (fileId == null) { + this._options.request.params = params; + } + else { + this._paramsStore.setParams(params, fileId); + } + }, + setEndpoint: function (endpoint, fileId) { + /*jshint eqeqeq: true, eqnull: true*/ + if (fileId == null) { + this._options.request.endpoint = endpoint; + } + else { + this._endpointStore.setEndpoint(endpoint, fileId); + } + }, + getInProgress: function () { + return this._filesInProgress.length; + }, + uploadStoredFiles: function () { + "use strict"; + var idToUpload; + + while (this._storedFileIds.length) { + idToUpload = this._storedFileIds.shift(); + this._filesInProgress.push(idToUpload); + this._handler.upload(idToUpload); + } + }, + clearStoredFiles: function () { + this._storedFileIds = []; + }, + retry: function (id) { + if (this._onBeforeManualRetry(id)) { + this._handler.retry(id); + return true; + } + else { + return false; + } + }, + cancel: function (fileId) { + this._handler.cancel(fileId); + }, + reset: function () { + this.log("Resetting uploader..."); + this._handler.reset(); + this._filesInProgress = []; + this._storedFileIds = []; + this._autoRetries = []; + this._retryTimeouts = []; + this._preventRetries = []; + this._button.reset(); + this._paramsStore.reset(); + this._endpointStore.reset(); + }, + addFiles: function (filesOrInputs) { + var self = this, + verifiedFilesOrInputs = [], + index, fileOrInput; + + if (filesOrInputs) { + if (!window.FileList || !(filesOrInputs instanceof FileList)) { + filesOrInputs = [].concat(filesOrInputs); + } + + for (index = 0; index < filesOrInputs.length; index += 1) { + fileOrInput = filesOrInputs[index]; + + if (qq.isFileOrInput(fileOrInput)) { + verifiedFilesOrInputs.push(fileOrInput); + } + else { + self.log(fileOrInput + ' is not a File or INPUT element! Ignoring!', 'warn'); + } + } + + this.log('Processing ' + verifiedFilesOrInputs.length + ' files or inputs...'); + this._uploadFileList(verifiedFilesOrInputs); + } + }, + getUuid: function (fileId) { + return this._handler.getUuid(fileId); + }, + getResumableFilesData: function () { + return this._handler.getResumableFilesData(); + }, + getSize: function (fileId) { + return this._handler.getSize(fileId); + }, + getFile: function (fileId) { + return this._handler.getFile(fileId); + }, + _createUploadButton: function (element) { + var self = this; + + var button = new qq.UploadButton({ + element: element, + multiple: this._options.multiple && qq.isXhrUploadSupported(), + acceptFiles: this._options.validation.acceptFiles, + onChange: function (input) { + self._onInputChange(input); + }, + hoverClass: this._options.classes.buttonHover, + focusClass: this._options.classes.buttonFocus + }); + + this._disposeSupport.addDisposer(function () { + button.dispose(); + }); + return button; + }, + _createUploadHandler: function () { + var self = this; + + return new qq.UploadHandler({ + debug: this._options.debug, + forceMultipart: this._options.request.forceMultipart, + maxConnections: this._options.maxConnections, + customHeaders: this._options.request.customHeaders, + inputName: this._options.request.inputName, + uuidParamName: this._options.request.uuidName, + totalFileSizeParamName: this._options.request.totalFileSizeName, + demoMode: this._options.demoMode, + paramsInBody: this._options.request.paramsInBody, + paramsStore: this._paramsStore, + endpointStore: this._endpointStore, + chunking: this._options.chunking, + resume: this._options.resume, + log: function (str, level) { + self.log(str, level); + }, + onProgress: function (id, fileName, loaded, total) { + self._onProgress(id, fileName, loaded, total); + self._options.callbacks.onProgress(id, fileName, loaded, total); + }, + onComplete: function (id, fileName, result, xhr) { + self._onComplete(id, fileName, result, xhr); + self._options.callbacks.onComplete(id, fileName, result); + }, + onCancel: function (id, fileName) { + self._onCancel(id, fileName); + self._options.callbacks.onCancel(id, fileName); + }, + onUpload: function (id, fileName) { + self._onUpload(id, fileName); + self._options.callbacks.onUpload(id, fileName); + }, + onUploadChunk: function (id, fileName, chunkData) { + self._options.callbacks.onUploadChunk(id, fileName, chunkData); + }, + onResume: function (id, fileName, chunkData) { + return self._options.callbacks.onResume(id, fileName, chunkData); + }, + onAutoRetry: function (id, fileName, responseJSON, xhr) { + self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty]; + + if (self._shouldAutoRetry(id, fileName, responseJSON)) { + self._maybeParseAndSendUploadError(id, fileName, responseJSON, xhr); + self._options.callbacks.onAutoRetry(id, fileName, self._autoRetries[id] + 1); + self._onBeforeAutoRetry(id, fileName); + + self._retryTimeouts[id] = setTimeout(function () { + self._onAutoRetry(id, fileName, responseJSON) + }, self._options.retry.autoAttemptDelay * 1000); + + return true; + } + else { + return false; + } + } + }); + }, + _preventLeaveInProgress: function () { + var self = this; + + this._disposeSupport.attach(window, 'beforeunload', function (e) { + if (!self._filesInProgress.length) { + return; + } + + var e = e || window.event; + // for ie, ff + e.returnValue = self._options.messages.onLeave; + // for webkit + return self._options.messages.onLeave; + }); + }, + _onSubmit: function (id, fileName) { + if (this._options.autoUpload) { + this._filesInProgress.push(id); + } + }, + _onProgress: function (id, fileName, loaded, total) { + }, + _onComplete: function (id, fileName, result, xhr) { + this._removeFromFilesInProgress(id); + this._maybeParseAndSendUploadError(id, fileName, result, xhr); + }, + _onCancel: function (id, fileName) { + this._removeFromFilesInProgress(id); + + clearTimeout(this._retryTimeouts[id]); + + var storedFileIndex = qq.indexOf(this._storedFileIds, id); + if (!this._options.autoUpload && storedFileIndex >= 0) { + this._storedFileIds.splice(storedFileIndex, 1); + } + }, + _removeFromFilesInProgress: function (id) { + var index = qq.indexOf(this._filesInProgress, id); + if (index >= 0) { + this._filesInProgress.splice(index, 1); + } + }, + _onUpload: function (id, fileName) { + }, + _onInputChange: function (input) { + if (qq.isXhrUploadSupported()) { + this.addFiles(input.files); + } else { + this.addFiles(input); + } + this._button.reset(); + }, + _onBeforeAutoRetry: function (id, fileName) { + this.log("Waiting " + this._options.retry.autoAttemptDelay + " seconds before retrying " + fileName + "..."); + }, + _onAutoRetry: function (id, fileName, responseJSON) { + this.log("Retrying " + fileName + "..."); + this._autoRetries[id]++; + this._handler.retry(id); + }, + _shouldAutoRetry: function (id, fileName, responseJSON) { + if (!this._preventRetries[id] && this._options.retry.enableAuto) { + if (this._autoRetries[id] === undefined) { + this._autoRetries[id] = 0; + } + + return this._autoRetries[id] < this._options.retry.maxAutoAttempts + } + + return false; + }, + //return false if we should not attempt the requested retry + _onBeforeManualRetry: function (id) { + if (this._preventRetries[id]) { + this.log("Retries are forbidden for id " + id, 'warn'); + return false; + } + else if (this._handler.isValid(id)) { + var fileName = this._handler.getName(id); + + if (this._options.callbacks.onManualRetry(id, fileName) === false) { + return false; + } + + this.log("Retrying upload for '" + fileName + "' (id: " + id + ")..."); + this._filesInProgress.push(id); + return true; + } + else { + this.log("'" + id + "' is not a valid file ID", 'error'); + return false; + } + }, + _maybeParseAndSendUploadError: function (id, fileName, response, xhr) { + //assuming no one will actually set the response code to something other than 200 and still set 'success' to true + if (!response.success) { + if (xhr && xhr.status !== 200 && !response.error) { + this._options.callbacks.onError(id, fileName, "XHR returned response code " + xhr.status); + } + else { + var errorReason = response.error ? response.error : "Upload failure reason unknown"; + this._options.callbacks.onError(id, fileName, errorReason); + } + } + }, + _uploadFileList: function (files) { + var validationDescriptors, index, batchInvalid; + + validationDescriptors = this._getValidationDescriptors(files); + batchInvalid = this._options.callbacks.onValidateBatch(validationDescriptors) === false; + + if (!batchInvalid) { + if (files.length > 0) { + for (index = 0; index < files.length; index++) { + if (this._validateFile(files[index])) { + this._uploadFile(files[index]); + } else { + if (this._options.validation.stopOnFirstInvalidFile) { + return; + } + } + } + } + else { + this._error('noFilesError', ""); + } + } + }, + _uploadFile: function (fileContainer) { + var id = this._handler.add(fileContainer); + var fileName = this._handler.getName(id); + + if (this._options.callbacks.onSubmit(id, fileName) !== false) { + this._onSubmit(id, fileName); + if (this._options.autoUpload) { + this._handler.upload(id); + } + else { + this._storeFileForLater(id); + } + } + }, + _storeFileForLater: function (id) { + this._storedFileIds.push(id); + }, + _validateFile: function (file) { + var validationDescriptor, name, size; + + validationDescriptor = this._getValidationDescriptor(file); + name = validationDescriptor.name; + size = validationDescriptor.size; + + if (this._options.callbacks.onValidate(validationDescriptor) === false) { + return false; + } + + if (!this._isAllowedExtension(name)) { + this._error('typeError', name); + return false; + + } + else if (size === 0) { + this._error('emptyError', name); + return false; + + } + else if (size && this._options.validation.sizeLimit && size > this._options.validation.sizeLimit) { + this._error('sizeError', name); + return false; + + } + else if (size && size < this._options.validation.minSizeLimit) { + this._error('minSizeError', name); + return false; + } + + return true; + }, + _error: function (code, fileName) { + var message = this._options.messages[code]; + + function r(name, replacement) { + message = message.replace(name, replacement); + } + + var extensions = this._options.validation.allowedExtensions.join(', ').toLowerCase(); + + r('{file}', this._options.formatFileName(fileName)); + r('{extensions}', extensions); + r('{sizeLimit}', this._formatSize(this._options.validation.sizeLimit)); + r('{minSizeLimit}', this._formatSize(this._options.validation.minSizeLimit)); + + this._options.callbacks.onError(null, fileName, message); + + return message; + }, + _isAllowedExtension: function (fileName) { + var allowed = this._options.validation.allowedExtensions, + valid = false; + + if (!allowed.length) { + return true; + } + + qq.each(allowed, function (idx, allowedExt) { + /*jshint eqeqeq: true, eqnull: true*/ + var extRegex = new RegExp('\\.' + allowedExt + "$", 'i'); + + if (fileName.match(extRegex) != null) { + valid = true; + return false; + } + }); + + return valid; + }, + _formatSize: function (bytes) { + var i = -1; + do { + bytes = bytes / 1024; + i++; + } while (bytes > 99); + + return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i]; + }, + _wrapCallbacks: function () { + var self, safeCallback; + + self = this; + + safeCallback = function (name, callback, args) { + try { + return callback.apply(self, args); + } + catch (exception) { + self.log("Caught exception in '" + name + "' callback - " + exception.message, 'error'); + } + } + + for (var prop in this._options.callbacks) { + (function () { + var callbackName, callbackFunc; + callbackName = prop; + callbackFunc = self._options.callbacks[callbackName]; + self._options.callbacks[callbackName] = function () { + return safeCallback(callbackName, callbackFunc, arguments); + } + }()); + } + }, + _parseFileName: function (file) { + var name; + + if (file.value) { + // it is a file input + // get input value and remove path to normalize + name = file.value.replace(/.*(\/|\\)/, ""); + } else { + // fix missing properties in Safari 4 and firefox 11.0a2 + name = (file.fileName !== null && file.fileName !== undefined) ? file.fileName : file.name; + } + + return name; + }, + _parseFileSize: function (file) { + var size; + + if (!file.value) { + // fix missing properties in Safari 4 and firefox 11.0a2 + size = (file.fileSize !== null && file.fileSize !== undefined) ? file.fileSize : file.size; + } + + return size; + }, + _getValidationDescriptor: function (file) { + var name, size, fileDescriptor; + + fileDescriptor = {}; + name = this._parseFileName(file); + size = this._parseFileSize(file); + + fileDescriptor.name = name; + if (size) { + fileDescriptor.size = size; + } + + return fileDescriptor; + }, + _getValidationDescriptors: function (files) { + var self = this, + fileDescriptors = []; + + qq.each(files, function (idx, file) { + fileDescriptors.push(self._getValidationDescriptor(file)); + }); + + return fileDescriptors; + }, + _createParamsStore: function () { + var paramsStore = {}, + self = this; + + return { + setParams: function (params, fileId) { + var paramsCopy = {}; + qq.extend(paramsCopy, params); + paramsStore[fileId] = paramsCopy; + }, + + getParams: function (fileId) { + /*jshint eqeqeq: true, eqnull: true*/ + var paramsCopy = {}; + + if (fileId != null && paramsStore[fileId]) { + qq.extend(paramsCopy, paramsStore[fileId]); + } + else { + qq.extend(paramsCopy, self._options.request.params); + } + + return paramsCopy; + }, + + remove: function (fileId) { + return delete paramsStore[fileId]; + }, + + reset: function () { + paramsStore = {}; + } + }; + }, + _createEndpointStore: function () { + var endpointStore = {}, + self = this; + + return { + setEndpoint: function (endpoint, fileId) { + endpointStore[fileId] = endpoint; + }, + + getEndpoint: function (fileId) { + /*jshint eqeqeq: true, eqnull: true*/ + if (fileId != null && endpointStore[fileId]) { + return endpointStore[fileId]; + } + + return self._options.request.endpoint; + }, + + remove: function (fileId) { + return delete endpointStore[fileId]; + }, + + reset: function () { + endpointStore = {}; + } + }; + } +}; +/*globals qq, document*/ +qq.DragAndDrop = function (o) { + "use strict"; + + var options, dz, dirPending, + droppedFiles = [], + droppedEntriesCount = 0, + droppedEntriesParsedCount = 0, + disposeSupport = new qq.DisposeSupport(); + + options = { + dropArea: null, + extraDropzones: [], + hideDropzones: true, + multiple: true, + classes: { + dropActive: null + }, + callbacks: { + dropProcessing: function (isProcessing, files) { + }, + error: function (code, filename) { + }, + log: function (message, level) { + } + } + }; + + qq.extend(options, o); + + function maybeUploadDroppedFiles() { + if (droppedEntriesCount === droppedEntriesParsedCount && !dirPending) { + options.callbacks.log('Grabbed ' + droppedFiles.length + " files after tree traversal."); + dz.dropDisabled(false); + options.callbacks.dropProcessing(false, droppedFiles); + } + } + + function addDroppedFile(file) { + droppedFiles.push(file); + droppedEntriesParsedCount += 1; + maybeUploadDroppedFiles(); + } + + function traverseFileTree(entry) { + var dirReader, i; + + droppedEntriesCount += 1; + + if (entry.isFile) { + entry.file(function (file) { + addDroppedFile(file); + }); + } + else if (entry.isDirectory) { + dirPending = true; + dirReader = entry.createReader(); + dirReader.readEntries(function (entries) { + droppedEntriesParsedCount += 1; + for (i = 0; i < entries.length; i += 1) { + traverseFileTree(entries[i]); + } + + dirPending = false; + + if (!entries.length) { + maybeUploadDroppedFiles(); + } + }); + } + } + + function handleDataTransfer(dataTransfer) { + var i, items, entry; + + options.callbacks.dropProcessing(true); + dz.dropDisabled(true); + + if (dataTransfer.files.length > 1 && !options.multiple) { + options.callbacks.dropProcessing(false); + options.callbacks.error('tooManyFilesError', ""); + dz.dropDisabled(false); + } + else { + droppedFiles = []; + droppedEntriesCount = 0; + droppedEntriesParsedCount = 0; + + if (qq.isFolderDropSupported(dataTransfer)) { + items = dataTransfer.items; + + for (i = 0; i < items.length; i += 1) { + entry = items[i].webkitGetAsEntry(); + if (entry) { + //due to a bug in Chrome's File System API impl - #149735 + if (entry.isFile) { + droppedFiles.push(items[i].getAsFile()); + if (i === items.length - 1) { + maybeUploadDroppedFiles(); + } + } + + else { + traverseFileTree(entry); + } + } + } + } + else { + options.callbacks.dropProcessing(false, dataTransfer.files); + dz.dropDisabled(false); + } + } + } + + function setupDropzone(dropArea) { + dz = new qq.UploadDropZone({ + element: dropArea, + onEnter: function (e) { + qq(dropArea).addClass(options.classes.dropActive); + e.stopPropagation(); + }, + onLeaveNotDescendants: function (e) { + qq(dropArea).removeClass(options.classes.dropActive); + }, + onDrop: function (e) { + if (options.hideDropzones) { + qq(dropArea).hide(); + } + qq(dropArea).removeClass(options.classes.dropActive); + + handleDataTransfer(e.dataTransfer); + } + }); + + disposeSupport.addDisposer(function () { + dz.dispose(); + }); + + if (options.hideDropzones) { + qq(dropArea).hide(); + } + } + + function isFileDrag(dragEvent) { + var fileDrag; + + qq.each(dragEvent.dataTransfer.types, function (key, val) { + if (val === 'Files') { + fileDrag = true; + return false; + } + }); + + return fileDrag; + } + + function setupDragDrop() { + if (options.dropArea) { + options.extraDropzones.push(options.dropArea); + } + + var i, dropzones = options.extraDropzones; + + for (i = 0; i < dropzones.length; i += 1) { + setupDropzone(dropzones[i]); + } + + // IE <= 9 does not support the File API used for drag+drop uploads + if (options.dropArea && (!qq.ie() || qq.ie10())) { + disposeSupport.attach(document, 'dragenter', function (e) { + if (!dz.dropDisabled() && isFileDrag(e)) { + if (qq(options.dropArea).hasClass(options.classes.dropDisabled)) { + return; + } + + options.dropArea.style.display = 'block'; + for (i = 0; i < dropzones.length; i += 1) { + dropzones[i].style.display = 'block'; + } + } + }); + } + disposeSupport.attach(document, 'dragleave', function (e) { + if (options.hideDropzones && qq.FineUploader.prototype._leaving_document_out(e)) { + for (i = 0; i < dropzones.length; i += 1) { + qq(dropzones[i]).hide(); + } + } + }); + disposeSupport.attach(document, 'drop', function (e) { + if (options.hideDropzones) { + for (i = 0; i < dropzones.length; i += 1) { + qq(dropzones[i]).hide(); + } + } + e.preventDefault(); + }); + } + + return { + setup: function () { + setupDragDrop(); + }, + + setupExtraDropzone: function (element) { + options.extraDropzones.push(element); + setupDropzone(element); + }, + + removeExtraDropzone: function (element) { + var i, dzs = options.extraDropzones; + for (i in dzs) { + if (dzs[i] === element) { + return dzs.splice(i, 1); + } + } + }, + + dispose: function () { + disposeSupport.dispose(); + dz.dispose(); + } + }; +}; + + +qq.UploadDropZone = function (o) { + "use strict"; + + var options, element, preventDrop, dropOutsideDisabled, disposeSupport = new qq.DisposeSupport(); + + options = { + element: null, + onEnter: function (e) { + }, + onLeave: function (e) { + }, + // is not fired when leaving element by hovering descendants + onLeaveNotDescendants: function (e) { + }, + onDrop: function (e) { + } + }; + + qq.extend(options, o); + element = options.element; + + function dragover_should_be_canceled() { + return qq.safari() || (qq.firefox() && qq.windows()); + } + + function disableDropOutside(e) { + // run only once for all instances + if (!dropOutsideDisabled) { + + // for these cases we need to catch onDrop to reset dropArea + if (dragover_should_be_canceled) { + disposeSupport.attach(document, 'dragover', function (e) { + e.preventDefault(); + }); + } else { + disposeSupport.attach(document, 'dragover', function (e) { + if (e.dataTransfer) { + e.dataTransfer.dropEffect = 'none'; + e.preventDefault(); + } + }); + } + + dropOutsideDisabled = true; + } + } + + function isValidFileDrag(e) { + // e.dataTransfer currently causing IE errors + // IE9 does NOT support file API, so drag-and-drop is not possible + if (qq.ie() && !qq.ie10()) { + return false; + } + + var effectTest, dt = e.dataTransfer, + // do not check dt.types.contains in webkit, because it crashes safari 4 + isSafari = qq.safari(); + + // dt.effectAllowed is none in Safari 5 + // dt.types.contains check is for firefox + effectTest = qq.ie10() ? true : dt.effectAllowed !== 'none'; + return dt && effectTest && (dt.files || (!isSafari && dt.types.contains && dt.types.contains('Files'))); + } + + function isOrSetDropDisabled(isDisabled) { + if (isDisabled !== undefined) { + preventDrop = isDisabled; + } + return preventDrop; + } + + function attachEvents() { + disposeSupport.attach(element, 'dragover', function (e) { + if (!isValidFileDrag(e)) { + return; + } + + var effect = qq.ie() ? null : e.dataTransfer.effectAllowed; + if (effect === 'move' || effect === 'linkMove') { + e.dataTransfer.dropEffect = 'move'; // for FF (only move allowed) + } else { + e.dataTransfer.dropEffect = 'copy'; // for Chrome + } + + e.stopPropagation(); + e.preventDefault(); + }); + + disposeSupport.attach(element, 'dragenter', function (e) { + if (!isOrSetDropDisabled()) { + if (!isValidFileDrag(e)) { + return; + } + options.onEnter(e); + } + }); + + disposeSupport.attach(element, 'dragleave', function (e) { + if (!isValidFileDrag(e)) { + return; + } + + options.onLeave(e); + + var relatedTarget = document.elementFromPoint(e.clientX, e.clientY); + // do not fire when moving a mouse over a descendant + if (qq(this).contains(relatedTarget)) { + return; + } + + options.onLeaveNotDescendants(e); + }); + + disposeSupport.attach(element, 'drop', function (e) { + if (!isOrSetDropDisabled()) { + if (!isValidFileDrag(e)) { + return; + } + + e.preventDefault(); + options.onDrop(e); + } + }); + } + + disableDropOutside(); + attachEvents(); + + return { + dropDisabled: function (isDisabled) { + return isOrSetDropDisabled(isDisabled); + }, + + dispose: function () { + disposeSupport.dispose(); + } + }; +}; +/** + * Class that creates upload widget with drag-and-drop and file list + * @inherits qq.FineUploaderBasic + */ +qq.FineUploader = function (o) { + // call parent constructor + qq.FineUploaderBasic.apply(this, arguments); + + // additional options + qq.extend(this._options, { + element: null, + listElement: null, + dragAndDrop: { + extraDropzones: [], + hideDropzones: true, + disableDefaultDropzone: false + }, + text: { + uploadButton: 'Upload a file', + cancelButton: 'Cancel', + retryButton: 'Retry', + failUpload: 'Upload failed', + dragZone: 'Drop files here to upload', + dropProcessing: 'Processing dropped files...', + formatProgress: "{percent}% of {total_size}", + waitingForResponse: "Processing..." + }, + template: '
    ' + + ((!this._options.dragAndDrop || !this._options.dragAndDrop.disableDefaultDropzone) ? '
    {dragZoneText}
    ' : '') + + (!this._options.button ? '
    {uploadButtonText}
    ' : '') + + '{dropProcessingText}' + + (!this._options.listElement ? '
      ' : '') + + '
      ', + + // template for one item in file list + fileTemplate: '
    • ' + + '
      ' + + '' + + '' + + '' + + '' + + '{cancelButtonText}' + + '{retryButtonText}' + + '{statusText}' + + '
    • ', + classes: { + button: 'qq-upload-button', + drop: 'qq-upload-drop-area', + dropActive: 'qq-upload-drop-area-active', + dropDisabled: 'qq-upload-drop-area-disabled', + list: 'qq-upload-list', + progressBar: 'qq-progress-bar', + file: 'qq-upload-file', + spinner: 'qq-upload-spinner', + finished: 'qq-upload-finished', + retrying: 'qq-upload-retrying', + retryable: 'qq-upload-retryable', + size: 'qq-upload-size', + cancel: 'qq-upload-cancel', + retry: 'qq-upload-retry', + statusText: 'qq-upload-status-text', + + success: 'qq-upload-success', + fail: 'qq-upload-fail', + + successIcon: null, + failIcon: null, + + dropProcessing: 'qq-drop-processing', + dropProcessingSpinner: 'qq-drop-processing-spinner' + }, + failedUploadTextDisplay: { + mode: 'default', //default, custom, or none + maxChars: 50, + responseProperty: 'error', + enableTooltip: true + }, + messages: { + tooManyFilesError: "You may only drop one file" + }, + retry: { + showAutoRetryNote: true, + autoRetryNote: "Retrying {retryNum}/{maxAuto}...", + showButton: false + }, + showMessage: function (message) { + setTimeout(function () { + alert(message); + }, 0); + } + }, true); + + // overwrite options with user supplied + qq.extend(this._options, o, true); + this._wrapCallbacks(); + + // overwrite the upload button text if any + // same for the Cancel button and Fail message text + this._options.template = this._options.template.replace(/\{dragZoneText\}/g, this._options.text.dragZone); + this._options.template = this._options.template.replace(/\{uploadButtonText\}/g, this._options.text.uploadButton); + this._options.template = this._options.template.replace(/\{dropProcessingText\}/g, this._options.text.dropProcessing); + this._options.fileTemplate = this._options.fileTemplate.replace(/\{cancelButtonText\}/g, this._options.text.cancelButton); + this._options.fileTemplate = this._options.fileTemplate.replace(/\{retryButtonText\}/g, this._options.text.retryButton); + this._options.fileTemplate = this._options.fileTemplate.replace(/\{statusText\}/g, ""); + + this._element = this._options.element; + this._element.innerHTML = this._options.template; + this._listElement = this._options.listElement || this._find(this._element, 'list'); + + this._classes = this._options.classes; + + if (!this._button) { + this._button = this._createUploadButton(this._find(this._element, 'button')); + } + + this._bindCancelAndRetryEvents(); + + this._dnd = this._setupDragAndDrop(); +}; + +// inherit from Basic Uploader +qq.extend(qq.FineUploader.prototype, qq.FineUploaderBasic.prototype); + +qq.extend(qq.FineUploader.prototype, { + clearStoredFiles: function () { + qq.FineUploaderBasic.prototype.clearStoredFiles.apply(this, arguments); + this._listElement.innerHTML = ""; + }, + addExtraDropzone: function (element) { + this._dnd.setupExtraDropzone(element); + }, + removeExtraDropzone: function (element) { + return this._dnd.removeExtraDropzone(element); + }, + getItemByFileId: function (id) { + var item = this._listElement.firstChild; + + // there can't be txt nodes in dynamically created list + // and we can use nextSibling + while (item) { + if (item.qqFileId == id) return item; + item = item.nextSibling; + } + }, + cancel: function (fileId) { + qq.FineUploaderBasic.prototype.cancel.apply(this, arguments); + var item = this.getItemByFileId(fileId); + qq(item).remove(); + }, + reset: function () { + qq.FineUploaderBasic.prototype.reset.apply(this, arguments); + this._element.innerHTML = this._options.template; + this._listElement = this._options.listElement || this._find(this._element, 'list'); + if (!this._options.button) { + this._button = this._createUploadButton(this._find(this._element, 'button')); + } + this._bindCancelAndRetryEvents(); + this._dnd.dispose(); + this._dnd = this._setupDragAndDrop(); + }, + _setupDragAndDrop: function () { + var self = this, + dropProcessingEl = this._find(this._element, 'dropProcessing'), + dnd, preventSelectFiles, defaultDropAreaEl; + + preventSelectFiles = function (event) { + event.preventDefault(); + }; + + if (!this._options.dragAndDrop.disableDefaultDropzone) { + defaultDropAreaEl = this._find(this._options.element, 'drop'); + } + + dnd = new qq.DragAndDrop({ + dropArea: defaultDropAreaEl, + extraDropzones: this._options.dragAndDrop.extraDropzones, + hideDropzones: this._options.dragAndDrop.hideDropzones, + multiple: this._options.multiple, + classes: { + dropActive: this._options.classes.dropActive + }, + callbacks: { + dropProcessing: function (isProcessing, files) { + var input = self._button.getInput(); + + if (isProcessing) { + qq(dropProcessingEl).css({display: 'block'}); + qq(input).attach('click', preventSelectFiles); + } + else { + qq(dropProcessingEl).hide(); + qq(input).detach('click', preventSelectFiles); + } + + if (files) { + self.addFiles(files); + } + }, + error: function (code, filename) { + self._error(code, filename); + }, + log: function (message, level) { + self.log(message, level); + } + } + }); + + dnd.setup(); + + return dnd; + }, + _leaving_document_out: function (e) { + return ((qq.chrome() || (qq.safari() && qq.windows())) && e.clientX == 0 && e.clientY == 0) // null coords for Chrome and Safari Windows + || (qq.firefox() && !e.relatedTarget); // null e.relatedTarget for Firefox + }, + _storeFileForLater: function (id) { + qq.FineUploaderBasic.prototype._storeFileForLater.apply(this, arguments); + var item = this.getItemByFileId(id); + qq(this._find(item, 'spinner')).hide(); + }, + /** + * Gets one of the elements listed in this._options.classes + **/ + _find: function (parent, type) { + var element = qq(parent).getByClass(this._options.classes[type])[0]; + if (!element) { + throw new Error('element not found ' + type); + } + + return element; + }, + _onSubmit: function (id, fileName) { + qq.FineUploaderBasic.prototype._onSubmit.apply(this, arguments); + this._addToList(id, fileName); + }, + // Update the progress bar & percentage as the file is uploaded + _onProgress: function (id, fileName, loaded, total) { + qq.FineUploaderBasic.prototype._onProgress.apply(this, arguments); + + var item, progressBar, text, percent, cancelLink, size; + + item = this.getItemByFileId(id); + progressBar = this._find(item, 'progressBar'); + percent = Math.round(loaded / total * 100); + + if (loaded === total) { + cancelLink = this._find(item, 'cancel'); + qq(cancelLink).hide(); + + qq(progressBar).hide(); + qq(this._find(item, 'statusText')).setText(this._options.text.waitingForResponse); + + // If last byte was sent, just display final size + text = this._formatSize(total); + } + else { + // If still uploading, display percentage + text = this._formatProgress(loaded, total); + + qq(progressBar).css({display: 'block'}); + } + + // Update progress bar element + qq(progressBar).css({width: percent + '%'}); + + size = this._find(item, 'size'); + qq(size).css({display: 'inline'}); + qq(size).setText(text); + }, + _onComplete: function (id, fileName, result, xhr) { + qq.FineUploaderBasic.prototype._onComplete.apply(this, arguments); + + var item = this.getItemByFileId(id); + + qq(this._find(item, 'statusText')).clearText(); + + qq(item).removeClass(this._classes.retrying); + qq(this._find(item, 'progressBar')).hide(); + + if (!this._options.disableCancelForFormUploads || qq.isXhrUploadSupported()) { + qq(this._find(item, 'cancel')).hide(); + } + qq(this._find(item, 'spinner')).hide(); + + if (result.success) { + qq(item).addClass(this._classes.success); + if (this._classes.successIcon) { + this._find(item, 'finished').style.display = "inline-block"; + qq(item).addClass(this._classes.successIcon); + } + } else { + qq(item).addClass(this._classes.fail); + if (this._classes.failIcon) { + this._find(item, 'finished').style.display = "inline-block"; + qq(item).addClass(this._classes.failIcon); + } + if (this._options.retry.showButton && !this._preventRetries[id]) { + qq(item).addClass(this._classes.retryable); + } + this._controlFailureTextDisplay(item, result); + } + }, + _onUpload: function (id, fileName) { + qq.FineUploaderBasic.prototype._onUpload.apply(this, arguments); + + var item = this.getItemByFileId(id); + this._showSpinner(item); + }, + _onBeforeAutoRetry: function (id) { + var item, progressBar, cancelLink, failTextEl, retryNumForDisplay, maxAuto, retryNote; + + qq.FineUploaderBasic.prototype._onBeforeAutoRetry.apply(this, arguments); + + item = this.getItemByFileId(id); + progressBar = this._find(item, 'progressBar'); + + this._showCancelLink(item); + progressBar.style.width = 0; + qq(progressBar).hide(); + + if (this._options.retry.showAutoRetryNote) { + failTextEl = this._find(item, 'statusText'); + retryNumForDisplay = this._autoRetries[id] + 1; + maxAuto = this._options.retry.maxAutoAttempts; + + retryNote = this._options.retry.autoRetryNote.replace(/\{retryNum\}/g, retryNumForDisplay); + retryNote = retryNote.replace(/\{maxAuto\}/g, maxAuto); + + qq(failTextEl).setText(retryNote); + if (retryNumForDisplay === 1) { + qq(item).addClass(this._classes.retrying); + } + } + }, + //return false if we should not attempt the requested retry + _onBeforeManualRetry: function (id) { + if (qq.FineUploaderBasic.prototype._onBeforeManualRetry.apply(this, arguments)) { + var item = this.getItemByFileId(id); + this._find(item, 'progressBar').style.width = 0; + qq(item).removeClass(this._classes.fail); + qq(this._find(item, 'statusText')).clearText(); + this._showSpinner(item); + this._showCancelLink(item); + return true; + } + return false; + }, + _addToList: function (id, fileName) { + var item = qq.toElement(this._options.fileTemplate); + if (this._options.disableCancelForFormUploads && !qq.isXhrUploadSupported()) { + var cancelLink = this._find(item, 'cancel'); + qq(cancelLink).remove(); + } + + item.qqFileId = id; + + var fileElement = this._find(item, 'file'); + qq(fileElement).setText(this._options.formatFileName(fileName)); + qq(this._find(item, 'size')).hide(); + if (!this._options.multiple) this._clearList(); + this._listElement.appendChild(item); + }, + _clearList: function () { + this._listElement.innerHTML = ''; + this.clearStoredFiles(); + }, + /** + * delegate click event for cancel & retry links + **/ + _bindCancelAndRetryEvents: function () { + var self = this, + list = this._listElement; + + this._disposeSupport.attach(list, 'click', function (e) { + e = e || window.event; + var target = e.target || e.srcElement; + + if (qq(target).hasClass(self._classes.cancel) || qq(target).hasClass(self._classes.retry)) { + qq.preventDefault(e); + + var item = target.parentNode; + while (item.qqFileId == undefined) { + item = target = target.parentNode; + } + + if (qq(target).hasClass(self._classes.cancel)) { + self.cancel(item.qqFileId); + } + else { + qq(item).removeClass(self._classes.retryable); + self.retry(item.qqFileId); + } + } + }); + }, + _formatProgress: function (uploadedSize, totalSize) { + var message = this._options.text.formatProgress; + + function r(name, replacement) { + message = message.replace(name, replacement); + } + + r('{percent}', Math.round(uploadedSize / totalSize * 100)); + r('{total_size}', this._formatSize(totalSize)); + return message; + }, + _controlFailureTextDisplay: function (item, response) { + var mode, maxChars, responseProperty, failureReason, shortFailureReason; + + mode = this._options.failedUploadTextDisplay.mode; + maxChars = this._options.failedUploadTextDisplay.maxChars; + responseProperty = this._options.failedUploadTextDisplay.responseProperty; + + if (mode === 'custom') { + failureReason = response[responseProperty]; + if (failureReason) { + if (failureReason.length > maxChars) { + shortFailureReason = failureReason.substring(0, maxChars) + '...'; + } + } + else { + failureReason = this._options.text.failUpload; + this.log("'" + responseProperty + "' is not a valid property on the server response.", 'warn'); + } + + qq(this._find(item, 'statusText')).setText(shortFailureReason || failureReason); + + if (this._options.failedUploadTextDisplay.enableTooltip) { + this._showTooltip(item, failureReason); + } + } + else if (mode === 'default') { + qq(this._find(item, 'statusText')).setText(this._options.text.failUpload); + } + else if (mode !== 'none') { + this.log("failedUploadTextDisplay.mode value of '" + mode + "' is not valid", 'warn'); + } + }, + //TODO turn this into a real tooltip, with click trigger (so it is usable on mobile devices). See case #355 for details. + _showTooltip: function (item, text) { + item.title = text; + }, + _showSpinner: function (item) { + var spinnerEl = this._find(item, 'spinner'); + spinnerEl.style.display = "inline-block"; + }, + _showCancelLink: function (item) { + if (!this._options.disableCancelForFormUploads || qq.isXhrUploadSupported()) { + var cancelLink = this._find(item, 'cancel'); + cancelLink.style.display = 'inline'; + } + }, + _error: function (code, fileName) { + var message = qq.FineUploaderBasic.prototype._error.apply(this, arguments); + this._options.showMessage(message); + } +}); +/*globals jQuery, qq*/ +(function ($) { + "use strict"; + var uploader, $el, init, dataStore, pluginOption, pluginOptions, addCallbacks, transformVariables, isValidCommand, + delegateCommand; + + pluginOptions = ['uploaderType']; + + init = function (options) { + if (options) { + var xformedOpts = transformVariables(options); + addCallbacks(xformedOpts); + + if (pluginOption('uploaderType') === 'basic') { + uploader(new qq.FineUploaderBasic(xformedOpts)); + } + else { + uploader(new qq.FineUploader(xformedOpts)); + } + } + + return $el; + }; + + dataStore = function (key, val) { + var data = $el.data('fineuploader'); + + if (val) { + if (data === undefined) { + data = {}; + } + data[key] = val; + $el.data('fineuploader', data); + } + else { + if (data === undefined) { + return null; + } + return data[key]; + } + }; + + //the underlying Fine Uploader instance is stored in jQuery's data stored, associated with the element + // tied to this instance of the plug-in + uploader = function (instanceToStore) { + return dataStore('uploader', instanceToStore); + }; + + pluginOption = function (option, optionVal) { + return dataStore(option, optionVal); + }; + + //implement all callbacks defined in Fine Uploader as functions that trigger appropriately names events and + // return the result of executing the bound handler back to Fine Uploader + addCallbacks = function (transformedOpts) { + var callbacks = transformedOpts.callbacks = {}; + + $.each(new qq.FineUploaderBasic()._options.callbacks, function (prop, func) { + var name, $callbackEl; + + name = /^on(\w+)/.exec(prop)[1]; + name = name.substring(0, 1).toLowerCase() + name.substring(1); + $callbackEl = $el; + + callbacks[prop] = function () { + var args = Array.prototype.slice.call(arguments); + return $callbackEl.triggerHandler(name, args); + }; + }); + }; + + //transform jQuery objects into HTMLElements, and pass along all other option properties + transformVariables = function (source, dest) { + var xformed, arrayVals; + + if (dest === undefined) { + if (source.uploaderType !== 'basic') { + xformed = { element: $el[0] }; + } + else { + xformed = {}; + } + } + else { + xformed = dest; + } + + $.each(source, function (prop, val) { + if ($.inArray(prop, pluginOptions) >= 0) { + pluginOption(prop, val); + } + else if (val instanceof $) { + xformed[prop] = val[0]; + } + else if ($.isPlainObject(val)) { + xformed[prop] = {}; + transformVariables(val, xformed[prop]); + } + else if ($.isArray(val)) { + arrayVals = []; + $.each(val, function (idx, arrayVal) { + if (arrayVal instanceof $) { + $.merge(arrayVals, arrayVal); + } + else { + arrayVals.push(arrayVal); + } + }); + xformed[prop] = arrayVals; + } + else { + xformed[prop] = val; + } + }); + + if (dest === undefined) { + return xformed; + } + }; + + isValidCommand = function (command) { + return $.type(command) === "string" && !command.match(/^_/) && //enforce private methods convention + uploader()[command] !== undefined; + }; + + //assuming we have already verified that this is a valid command, call the associated function in the underlying + // Fine Uploader instance (passing along the arguments from the caller) and return the result of the call back to the caller + delegateCommand = function (command) { + var xformedArgs = [], origArgs = Array.prototype.slice.call(arguments, 1); + + transformVariables(origArgs, xformedArgs); + + return uploader()[command].apply(uploader(), xformedArgs); + }; + + $.fn.fineUploader = function (optionsOrCommand) { + var self = this, selfArgs = arguments, retVals = []; + + this.each(function (index, el) { + $el = $(el); + + if (uploader() && isValidCommand(optionsOrCommand)) { + retVals.push(delegateCommand.apply(self, selfArgs)); + + if (self.length === 1) { + return false; + } + } + else if (typeof optionsOrCommand === 'object' || !optionsOrCommand) { + init.apply(self, selfArgs); + } + else { + $.error('Method ' + optionsOrCommand + ' does not exist on jQuery.fineUploader'); + } + }); + + if (retVals.length === 1) { + return retVals[0]; + } + else if (retVals.length > 1) { + return retVals; + } + + return this; + }; + +}(jQuery)); \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/js/jquery.fineuploader-3.2.min.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/js/jquery.fineuploader-3.2.min.js new file mode 100644 index 0000000..e578e20 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/fineuploader/assets/js/jquery.fineuploader-3.2.min.js @@ -0,0 +1,1994 @@ +var qq = function (e) { + "use strict"; + return{hide: function () { + e.style.display = "none"; + return this + }, attach: function (t, n) { + if (e.addEventListener) { + e.addEventListener(t, n, false) + } else if (e.attachEvent) { + e.attachEvent("on" + t, n) + } + return function () { + qq(e).detach(t, n) + } + }, detach: function (t, n) { + if (e.removeEventListener) { + e.removeEventListener(t, n, false) + } else if (e.attachEvent) { + e.detachEvent("on" + t, n) + } + return this + }, contains: function (t) { + if (e === t) { + return true + } + if (e.contains) { + return e.contains(t) + } else { + return!!(t.compareDocumentPosition(e) & 8) + } + }, insertBefore: function (t) { + t.parentNode.insertBefore(e, t); + return this + }, remove: function () { + e.parentNode.removeChild(e); + return this + }, css: function (t) { + if (t.opacity !== null) { + if (typeof e.style.opacity !== "string" && typeof e.filters !== "undefined") { + t.filter = "alpha(opacity=" + Math.round(100 * t.opacity) + ")" + } + } + qq.extend(e.style, t); + return this + }, hasClass: function (t) { + var n = new RegExp("(^| )" + t + "( |$)"); + return n.test(e.className) + }, addClass: function (t) { + if (!qq(e).hasClass(t)) { + e.className += " " + t + } + return this + }, removeClass: function (t) { + var n = new RegExp("(^| )" + t + "( |$)"); + e.className = e.className.replace(n, " ").replace(/^\s+|\s+$/g, ""); + return this + }, getByClass: function (t) { + var n, r = []; + if (e.querySelectorAll) { + return e.querySelectorAll("." + t) + } + n = e.getElementsByTagName("*"); + qq.each(n, function (e, n) { + if (qq(n).hasClass(t)) { + r.push(n) + } + }); + return r + }, children: function () { + var t = [], n = e.firstChild; + while (n) { + if (n.nodeType === 1) { + t.push(n) + } + n = n.nextSibling + } + return t + }, setText: function (t) { + e.innerText = t; + e.textContent = t; + return this + }, clearText: function () { + return qq(e).setText("") + }} +}; +qq.log = function (e, t) { + "use strict"; + if (window.console) { + if (!t || t === "info") { + window.console.log(e) + } else { + if (window.console[t]) { + window.console[t](e) + } else { + window.console.log("<" + t + "> " + e) + } + } + } +}; +qq.isObject = function (e) { + "use strict"; + return e !== null && e && typeof e === "object" && e.constructor === Object +}; +qq.isFunction = function (e) { + "use strict"; + return typeof e === "function" +}; +qq.isFileOrInput = function (e) { + "use strict"; + if (window.File && e instanceof File) { + return true + } else if (window.HTMLInputElement) { + if (e instanceof HTMLInputElement) { + if (e.type && e.type.toLowerCase() === "file") { + return true + } + } + } else if (e.tagName) { + if (e.tagName.toLowerCase() === "input") { + if (e.type && e.type.toLowerCase() === "file") { + return true + } + } + } + return false +}; +qq.isXhrUploadSupported = function () { + "use strict"; + var e = document.createElement("input"); + e.type = "file"; + return e.multiple !== undefined && typeof File !== "undefined" && typeof FormData !== "undefined" && typeof (new XMLHttpRequest).upload !== "undefined" +}; +qq.isFolderDropSupported = function (e) { + "use strict"; + return e.items && e.items[0].webkitGetAsEntry +}; +qq.isFileChunkingSupported = function () { + "use strict"; + return!qq.android() && qq.isXhrUploadSupported() && (File.prototype.slice || File.prototype.webkitSlice || File.prototype.mozSlice) +}; +qq.extend = function (e, t, n) { + "use strict"; + qq.each(t, function (t, r) { + if (n && qq.isObject(r)) { + if (e[t] === undefined) { + e[t] = {} + } + qq.extend(e[t], r, true) + } else { + e[t] = r + } + }) +}; +qq.indexOf = function (e, t, n) { + "use strict"; + if (e.indexOf) { + return e.indexOf(t, n) + } + n = n || 0; + var r = e.length; + if (n < 0) { + n += r + } + for (; n < r; n += 1) { + if (e.hasOwnProperty(n) && e[n] === t) { + return n + } + } + return-1 +}; +qq.getUniqueId = function () { + "use strict"; + return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (e) { + var t = Math.random() * 16 | 0, n = e == "x" ? t : t & 3 | 8; + return n.toString(16) + }) +}; +qq.ie = function () { + "use strict"; + return navigator.userAgent.indexOf("MSIE") !== -1 +}; +qq.ie10 = function () { + "use strict"; + return navigator.userAgent.indexOf("MSIE 10") !== -1 +}; +qq.safari = function () { + "use strict"; + return navigator.vendor !== undefined && navigator.vendor.indexOf("Apple") !== -1 +}; +qq.chrome = function () { + "use strict"; + return navigator.vendor !== undefined && navigator.vendor.indexOf("Google") !== -1 +}; +qq.firefox = function () { + "use strict"; + return navigator.userAgent.indexOf("Mozilla") !== -1 && navigator.vendor !== undefined && navigator.vendor === "" +}; +qq.windows = function () { + "use strict"; + return navigator.platform === "Win32" +}; +qq.android = function () { + "use strict"; + return navigator.userAgent.toLowerCase().indexOf("android") !== -1 +}; +qq.preventDefault = function (e) { + "use strict"; + if (e.preventDefault) { + e.preventDefault() + } else { + e.returnValue = false + } +}; +qq.toElement = function () { + "use strict"; + var e = document.createElement("div"); + return function (t) { + e.innerHTML = t; + var n = e.firstChild; + e.removeChild(n); + return n + } +}(); +qq.each = function (e, t) { + "use strict"; + var n, r; + if (e) { + for (n in e) { + if (Object.prototype.hasOwnProperty.call(e, n)) { + r = t(n, e[n]); + if (r === false) { + break + } + } + } + } +}; +qq.obj2url = function (e, t, n) { + "use strict"; + var r, i, s = [], o = "&", u = function (e, n) { + var r = t ? /\[\]$/.test(t) ? t : t + "[" + n + "]" : n; + if (r !== "undefined" && n !== "undefined") { + s.push(typeof e === "object" ? qq.obj2url(e, r, true) : Object.prototype.toString.call(e) === "[object Function]" ? encodeURIComponent(r) + "=" + encodeURIComponent(e()) : encodeURIComponent(r) + "=" + encodeURIComponent(e)) + } + }; + if (!n && t) { + o = /\?/.test(t) ? /\?$/.test(t) ? "" : "&" : "?"; + s.push(t); + s.push(qq.obj2url(e)) + } else if (Object.prototype.toString.call(e) === "[object Array]" && typeof e !== "undefined") { + for (r = -1, i = e.length; r < i; r += 1) { + u(e[r], r) + } + } else if (typeof e !== "undefined" && e !== null && typeof e === "object") { + for (r in e) { + if (e.hasOwnProperty(r)) { + u(e[r], r) + } + } + } else { + s.push(encodeURIComponent(t) + "=" + encodeURIComponent(e)) + } + if (t) { + return s.join(o) + } else { + return s.join(o).replace(/^&/, "").replace(/%20/g, "+") + } +}; +qq.obj2FormData = function (e, t, n) { + "use strict"; + if (!t) { + t = new FormData + } + qq.each(e, function (e, r) { + e = n ? n + "[" + e + "]" : e; + if (qq.isObject(r)) { + qq.obj2FormData(r, t, e) + } else if (qq.isFunction(r)) { + t.append(encodeURIComponent(e), encodeURIComponent(r())) + } else { + t.append(encodeURIComponent(e), encodeURIComponent(r)) + } + }); + return t +}; +qq.obj2Inputs = function (e, t) { + "use strict"; + var n; + if (!t) { + t = document.createElement("form") + } + qq.obj2FormData(e, {append: function (e, r) { + n = document.createElement("input"); + n.setAttribute("name", e); + n.setAttribute("value", r); + t.appendChild(n) + }}); + return t +}; +qq.setCookie = function (e, t, n) { + var r = new Date, i = ""; + if (n) { + r.setTime(r.getTime() + n * 24 * 60 * 60 * 1e3); + i = "; expires=" + r.toGMTString() + } + document.cookie = e + "=" + t + i + "; path=/" +}; +qq.getCookie = function (e) { + var t = e + "=", n = document.cookie.split(";"), r; + for (var i = 0; i < n.length; i++) { + r = n[i]; + while (r.charAt(0) == " ") { + r = r.substring(1, r.length) + } + if (r.indexOf(t) === 0) { + return r.substring(t.length, r.length) + } + } +}; +qq.getCookieNames = function (e) { + var t = document.cookie.split(";"), n = []; + qq.each(t, function (t, r) { + r = r.trim(); + var i = r.indexOf("="); + if (r.match(e)) { + n.push(r.substr(0, i)) + } + }); + return n +}; +qq.deleteCookie = function (e) { + qq.setCookie(e, "", -1) +}; +qq.areCookiesEnabled = function () { + var e = Math.random() * 1e5, t = "qqCookieTest:" + e; + qq.setCookie(t, 1); + if (qq.getCookie(t)) { + qq.deleteCookie(t); + return true + } + return false +}; +qq.parseJson = function (json) { + if (typeof JSON.parse === "function") { + return JSON.parse(json) + } else { + return eval("(" + json + ")") + } +}; +qq.DisposeSupport = function () { + "use strict"; + var e = []; + return{dispose: function () { + var t; + do { + t = e.shift(); + if (t) { + t() + } + } while (t) + }, attach: function () { + var e = arguments; + this.addDisposer(qq(e[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1))) + }, addDisposer: function (t) { + e.push(t) + }} +}; +qq.UploadButton = function (e) { + this._options = {element: null, multiple: false, acceptFiles: null, name: "file", onChange: function (e) { + }, hoverClass: "qq-upload-button-hover", focusClass: "qq-upload-button-focus"}; + qq.extend(this._options, e); + this._disposeSupport = new qq.DisposeSupport; + this._element = this._options.element; + qq(this._element).css({position: "relative", overflow: "hidden", direction: "ltr"}); + this._input = this._createInput() +}; +qq.UploadButton.prototype = {getInput: function () { + return this._input +}, reset: function () { + if (this._input.parentNode) { + qq(this._input).remove() + } + qq(this._element).removeClass(this._options.focusClass); + this._input = this._createInput() +}, _createInput: function () { + var e = document.createElement("input"); + if (this._options.multiple) { + e.setAttribute("multiple", "multiple") + } + if (this._options.acceptFiles)e.setAttribute("accept", this._options.acceptFiles); + e.setAttribute("type", "file"); + e.setAttribute("name", this._options.name); + qq(e).css({position: "absolute", right: 0, top: 0, fontFamily: "Arial", fontSize: "118px", margin: 0, padding: 0, cursor: "pointer", opacity: 0}); + this._element.appendChild(e); + var t = this; + this._disposeSupport.attach(e, "change", function () { + t._options.onChange(e) + }); + this._disposeSupport.attach(e, "mouseover", function () { + qq(t._element).addClass(t._options.hoverClass) + }); + this._disposeSupport.attach(e, "mouseout", function () { + qq(t._element).removeClass(t._options.hoverClass) + }); + this._disposeSupport.attach(e, "focus", function () { + qq(t._element).addClass(t._options.focusClass) + }); + this._disposeSupport.attach(e, "blur", function () { + qq(t._element).removeClass(t._options.focusClass) + }); + if (window.attachEvent) { + e.setAttribute("tabIndex", "-1") + } + return e +}}; +qq.UploadHandler = function (e) { + "use strict"; + var t = [], n, r, i, s; + n = {debug: false, forceMultipart: true, paramsInBody: false, paramsStore: {}, endpointStore: {}, maxConnections: 3, uuidParamName: "qquuid", totalFileSizeParamName: "qqtotalfilesize", chunking: {enabled: false, partSize: 2e6, paramNames: {partIndex: "qqpartindex", partByteOffset: "qqpartbyteoffset", chunkSize: "qqchunksize", totalParts: "qqtotalparts", filename: "qqfilename"}}, resume: {enabled: false, id: null, cookiesExpireIn: 7, paramNames: {resuming: "qqresume"}}, log: function (e, t) { + }, onProgress: function (e, t, n, r) { + }, onComplete: function (e, t, n, r) { + }, onCancel: function (e, t) { + }, onUpload: function (e, t) { + }, onUploadChunk: function (e, t, n) { + }, onAutoRetry: function (e, t, n, r) { + }, onResume: function (e, t, n) { + }}; + qq.extend(n, e); + r = n.log; + i = function (e) { + var r = qq.indexOf(t, e), i = n.maxConnections, o; + t.splice(r, 1); + if (t.length >= i && r < i) { + o = t[i - 1]; + s.upload(o) + } + }; + if (qq.isXhrUploadSupported()) { + s = new qq.UploadHandlerXhr(n, i, r) + } else { + s = new qq.UploadHandlerForm(n, i, r) + } + return{add: function (e) { + return s.add(e) + }, upload: function (e) { + var r = t.push(e); + if (r <= n.maxConnections) { + return s.upload(e) + } + }, retry: function (e) { + var n = qq.indexOf(t, e); + if (n >= 0) { + return s.upload(e, true) + } else { + return this.upload(e) + } + }, cancel: function (e) { + r("Cancelling " + e); + n.paramsStore.remove(e); + s.cancel(e); + i(e) + }, cancelAll: function () { + qq.each(t, function (e, t) { + this.cancel(t) + }); + t = [] + }, getName: function (e) { + return s.getName(e) + }, getSize: function (e) { + if (s.getSize) { + return s.getSize(e) + } + }, getFile: function (e) { + if (s.getFile) { + return s.getFile(e) + } + }, getQueue: function () { + return t + }, reset: function () { + r("Resetting upload handler"); + t = []; + s.reset() + }, getUuid: function (e) { + return s.getUuid(e) + }, isValid: function (e) { + return s.isValid(e) + }, getResumableFilesData: function () { + if (s.getResumableFilesData) { + return s.getResumableFilesData() + } + return[] + }} +}; +qq.UploadHandlerForm = function (o, uploadCompleteCallback, logCallback) { + "use strict"; + function attachLoadEvent(e, t) { + detachLoadEvents[e.id] = qq(e).attach("load", function () { + log("Received response for " + e.id); + if (!e.parentNode) { + return + } + try { + if (e.contentDocument && e.contentDocument.body && e.contentDocument.body.innerHTML == "false") { + return + } + } catch (n) { + log("Error when attempting to access iframe during handling of upload response (" + n + ")", "error") + } + t() + }) + } + + function getIframeContentJson(iframe) { + var response; + try { + var doc = iframe.contentDocument || iframe.contentWindow.document, innerHTML = doc.body.innerHTML; + log("converting iframe's innerHTML to JSON"); + log("innerHTML = " + innerHTML); + if (innerHTML && innerHTML.match(/^
      ');
      +        t.setAttribute("id", e);
      +        t.style.display = "none";
      +        document.body.appendChild(t);
      +        return t
      +    }
      +
      +    function createForm(e, t) {
      +        var n = options.paramsStore.getParams(e), r = options.demoMode ? "GET" : "POST", i = qq.toElement('
      '), s = options.endpointStore.getEndpoint(e), o = s; + n[options.uuidParamName] = uuids[e]; + if (!options.paramsInBody) { + o = qq.obj2url(n, s) + } else { + qq.obj2Inputs(n, i) + } + i.setAttribute("action", o); + i.setAttribute("target", t.name); + i.style.display = "none"; + document.body.appendChild(i); + return i + } + + var options = o, inputs = [], uuids = [], detachLoadEvents = {}, uploadComplete = uploadCompleteCallback, log = logCallback, api; + api = {add: function (e) { + e.setAttribute("name", options.inputName); + var t = inputs.push(e) - 1; + uuids[t] = qq.getUniqueId(); + if (e.parentNode) { + qq(e).remove() + } + return t + }, getName: function (e) { + return inputs[e].value.replace(/.*(\/|\\)/, "") + }, isValid: function (e) { + return inputs[e] !== undefined + }, reset: function () { + qq.UploadHandler.prototype.reset.apply(this, arguments); + inputs = []; + uuids = []; + detachLoadEvents = {} + }, getUuid: function (e) { + return uuids[e] + }, cancel: function (e) { + options.onCancel(e, this.getName(e)); + delete inputs[e]; + delete uuids[e]; + delete detachLoadEvents[e]; + var t = document.getElementById(e); + if (t) { + t.setAttribute("src", "java" + String.fromCharCode(115) + "cript:false;"); + qq(t).remove() + } + }, upload: function (e) { + var t = inputs[e], n = api.getName(e), r = createIframe(e), i = createForm(e, r); + if (!t) { + throw new Error("file with passed id was not added, or already uploaded or cancelled") + } + options.onUpload(e, this.getName(e)); + i.appendChild(t); + attachLoadEvent(r, function () { + log("iframe loaded"); + var t = getIframeContentJson(r); + setTimeout(function () { + detachLoadEvents[e](); + delete detachLoadEvents[e]; + qq(r).remove() + }, 1); + if (!t.success) { + if (options.onAutoRetry(e, n, t)) { + return + } + } + options.onComplete(e, n, t); + uploadComplete(e) + }); + log("Sending upload request for " + e); + i.submit(); + qq(i).remove(); + return e + }}; + return api +}; +qq.UploadHandlerXhr = function (e, t, n) { + "use strict"; + function p(e, t, n) { + var i = h.getSize(e), s = h.getName(e); + t[r.chunking.paramNames.partIndex] = n.part; + t[r.chunking.paramNames.partByteOffset] = n.start; + t[r.chunking.paramNames.chunkSize] = n.end - n.start; + t[r.chunking.paramNames.totalParts] = n.count; + t[r.totalFileSizeParamName] = i; + if (c) { + t[r.chunking.paramNames.filename] = s + } + } + + function d(e) { + e[r.resume.paramNames.resuming] = true + } + + function v(e, t, n) { + if (e.slice) { + return e.slice(t, n) + } else if (e.mozSlice) { + return e.mozSlice(t, n) + } else if (e.webkitSlice) { + return e.webkitSlice(t, n) + } + } + + function m(e, t) { + var n = r.chunking.partSize, i = h.getSize(e), s = o[e].file, u = n * t, a = u + n >= i ? i : u + n, f = g(e); + return{part: t, start: u, end: a, count: f, blob: v(s, u, a)} + } + + function g(e) { + var t = h.getSize(e), n = r.chunking.partSize; + return Math.ceil(t / n) + } + + function y(e) { + o[e].xhr = new XMLHttpRequest; + return o[e].xhr + } + + function b(e, t, n, i) { + var s = new FormData, u = r.demoMode ? "GET" : "POST", a = r.endpointStore.getEndpoint(i), f = a, l = h.getName(i), p = h.getSize(i); + e[r.uuidParamName] = o[i].uuid; + if (c) { + e[r.totalFileSizeParamName] = p + } + if (!r.paramsInBody) { + e[r.inputName] = l; + f = qq.obj2url(e, a) + } + t.open(u, f, true); + if (c) { + if (r.paramsInBody) { + qq.obj2FormData(e, s) + } + s.append(r.inputName, n); + return s + } + return n + } + + function w(e, t) { + var n = r.customHeaders, i = h.getName(e), s = o[e].file; + t.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + t.setRequestHeader("Cache-Control", "no-cache"); + if (!c) { + t.setRequestHeader("Content-Type", "application/octet-stream"); + t.setRequestHeader("X-Mime-Type", s.type) + } + qq.each(n, function (e, n) { + t.setRequestHeader(e, n) + }) + } + + function E(e, t, n) { + var s = h.getName(e), u = h.getSize(e); + o[e].attemptingResume = false; + r.onProgress(e, s, u, u); + r.onComplete(e, s, t, n); + delete o[e].xhr; + i(e) + } + + function S(e) { + var t = m(e, o[e].remainingChunkIdxs[0]), n = y(e), i = h.getSize(e), u = h.getName(e), a, f; + if (o[e].loaded === undefined) { + o[e].loaded = 0 + } + _(e, t); + n.onreadystatechange = M(e, n); + n.upload.onprogress = function (t) { + if (t.lengthComputable) { + if (o[e].loaded < i) { + var n = t.loaded + o[e].loaded; + r.onProgress(e, u, n, i) + } + } + }; + r.onUploadChunk(e, u, O(t)); + f = r.paramsStore.getParams(e); + p(e, f, t); + if (o[e].attemptingResume) { + d(f) + } + a = b(f, n, t.blob, e); + w(e, n); + s("Sending chunked upload request for " + e + ": bytes " + (t.start + 1) + "-" + t.end + " of " + i); + n.send(a) + } + + function x(e, t, n) { + var r = o[e].remainingChunkIdxs.shift(), i = m(e, r); + o[e].attemptingResume = false; + o[e].loaded += i.end - i.start; + if (o[e].remainingChunkIdxs.length > 0) { + S(e) + } else { + D(e); + E(e, t, n) + } + } + + function T(e, t) { + return e.status !== 200 || !t.success || t.reset + } + + function N(e) { + var t; + try { + t = qq.parseJson(e.responseText) + } catch (n) { + s("Error when attempting to parse xhr response text (" + n + ")", "error"); + t = {} + } + return t + } + + function C(e) { + s("Server has ordered chunking effort to be restarted on next attempt for file ID " + e, "error"); + if (f) { + D(e) + } + o[e].remainingChunkIdxs = []; + delete o[e].loaded + } + + function k(e) { + o[e].attemptingResume = false; + s("Server has declared that it cannot handle resume for file ID " + e + " - starting from the first chunk", "error"); + h.upload(e, true) + } + + function L(e, t, n) { + var i = h.getName(e); + if (r.onAutoRetry(e, i, t, n)) { + return + } else { + E(e, t, n) + } + } + + function A(e, t) { + var n; + if (!o[e]) { + return + } + s("xhr - server response received for " + e); + s("responseText = " + t.responseText); + n = N(t); + if (T(t, n)) { + if (n.reset) { + C(e) + } + if (o[e].attemptingResume && n.reset) { + k(e) + } else { + L(e, n, t) + } + } else if (a) { + x(e, n, t) + } else { + E(e, n, t) + } + } + + function O(e) { + return{partIndex: e.part, startByte: e.start + 1, endByte: e.end, totalParts: e.count} + } + + function M(e, t) { + return function () { + if (t.readyState === 4) { + A(e, t) + } + } + } + + function _(e, t) { + var n = h.getUuid(e), i = H(e), s = n + u + t.part, o = r.resume.cookiesExpireIn; + qq.setCookie(i, s, o) + } + + function D(e) { + var t = H(e); + qq.deleteCookie(t) + } + + function P(e) { + var t = qq.getCookie(H(e)), n, r, i; + if (t) { + n = t.indexOf(u); + r = t.substr(0, n); + i = parseInt(t.substr(n + 1, t.length - n), 10); + return{uuid: r, part: i} + } + } + + function H(e) { + var t = h.getName(e), n = h.getSize(e), i = r.chunking.partSize, s; + s = "qqfilechunk" + u + encodeURIComponent(t) + u + n + u + i; + if (l !== undefined) { + s += u + l + } + return s + } + + function B() { + if (r.resume.id !== null && r.resume.id !== undefined && !qq.isFunction(r.resume.id) && !qq.isObject(r.resume.id)) { + return r.resume.id + } + } + + function j(e, t) { + var n = h.getName(e), i = 0, u, a, l; + if (!o[e].remainingChunkIdxs || o[e].remainingChunkIdxs.length === 0) { + o[e].remainingChunkIdxs = []; + if (f && !t) { + u = P(e); + if (u) { + a = m(e, u.part); + if (r.onResume(e, n, O(a)) !== false) { + i = u.part; + o[e].uuid = u.uuid; + o[e].loaded = a.start; + o[e].attemptingResume = true; + s("Resuming " + n + " at partition index " + i) + } + } + } + for (l = g(e) - 1; l >= i; l -= 1) { + o[e].remainingChunkIdxs.unshift(l) + } + } + S(e) + } + + function F(e) { + var t = o[e].file, n = h.getName(e), i, u, a; + o[e].loaded = 0; + i = y(e); + i.upload.onprogress = function (t) { + if (t.lengthComputable) { + o[e].loaded = t.loaded; + r.onProgress(e, n, t.loaded, t.total) + } + }; + i.onreadystatechange = M(e, i); + u = r.paramsStore.getParams(e); + a = b(u, i, t, e); + w(e, i); + s("Sending upload request for " + e); + i.send(a) + } + + var r = e, i = t, s = n, o = [], u = "|", a = r.chunking.enabled && qq.isFileChunkingSupported(), f = r.resume.enabled && a && qq.areCookiesEnabled(), l = B(), c = r.forceMultipart || r.paramsInBody, h; + h = {add: function (e) { + if (!(e instanceof File)) { + throw new Error("Passed obj in not a File (in qq.UploadHandlerXhr)") + } + var t = o.push({file: e}) - 1; + o[t].uuid = qq.getUniqueId(); + return t + }, getName: function (e) { + var t = o[e].file; + return t.fileName !== null && t.fileName !== undefined ? t.fileName : t.name + }, getSize: function (e) { + var t = o[e].file; + return t.fileSize != null ? t.fileSize : t.size + }, getFile: function (e) { + if (o[e]) { + return o[e].file + } + }, getLoaded: function (e) { + return o[e].loaded || 0 + }, isValid: function (e) { + return o[e] !== undefined + }, reset: function () { + o = [] + }, getUuid: function (e) { + return o[e].uuid + }, upload: function (e, t) { + var n = this.getName(e); + r.onUpload(e, n); + if (a) { + j(e, t) + } else { + F(e) + } + }, cancel: function (e) { + r.onCancel(e, this.getName(e)); + if (o[e].xhr) { + o[e].xhr.abort() + } + if (f) { + D(e) + } + delete o[e] + }, getResumableFilesData: function () { + var e = [], t = []; + if (a && f) { + if (l === undefined) { + e = qq.getCookieNames(new RegExp("^qqfilechunk\\" + u + ".+\\" + u + "\\d+\\" + u + r.chunking.partSize + "=")) + } else { + e = qq.getCookieNames(new RegExp("^qqfilechunk\\" + u + ".+\\" + u + "\\d+\\" + u + r.chunking.partSize + "\\" + u + l + "=")) + } + qq.each(e, function (e, n) { + var r = n.split(u); + var i = qq.getCookie(n).split(u); + t.push({name: decodeURIComponent(r[1]), size: r[2], uuid: i[0], partIdx: i[1]}) + }); + return t + } + return[] + }}; + return h +}; +qq.FineUploaderBasic = function (e) { + var t = this; + this._options = {debug: false, button: null, multiple: true, maxConnections: 3, disableCancelForFormUploads: false, autoUpload: true, request: {endpoint: "/server/upload", params: {}, paramsInBody: false, customHeaders: {}, forceMultipart: true, inputName: "qqfile", uuidName: "qquuid", totalFileSizeName: "qqtotalfilesize"}, validation: {allowedExtensions: [], sizeLimit: 0, minSizeLimit: 0, stopOnFirstInvalidFile: true}, callbacks: {onSubmit: function (e, t) { + }, onComplete: function (e, t, n) { + }, onCancel: function (e, t) { + }, onUpload: function (e, t) { + }, onUploadChunk: function (e, t, n) { + }, onResume: function (e, t, n) { + }, onProgress: function (e, t, n, r) { + }, onError: function (e, t, n) { + }, onAutoRetry: function (e, t, n) { + }, onManualRetry: function (e, t) { + }, onValidateBatch: function (e) { + }, onValidate: function (e) { + }}, messages: {typeError: "{file} has an invalid extension. Valid extension(s): {extensions}.", sizeError: "{file} is too large, maximum file size is {sizeLimit}.", minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.", emptyError: "{file} is empty, please select files again without it.", noFilesError: "No files to upload.", onLeave: "The files are being uploaded, if you leave now the upload will be cancelled."}, retry: {enableAuto: false, maxAutoAttempts: 3, autoAttemptDelay: 5, preventRetryResponseProperty: "preventRetry"}, classes: {buttonHover: "qq-upload-button-hover", buttonFocus: "qq-upload-button-focus"}, chunking: {enabled: false, partSize: 2e6, paramNames: {partIndex: "qqpartindex", partByteOffset: "qqpartbyteoffset", chunkSize: "qqchunksize", totalFileSize: "qqtotalfilesize", totalParts: "qqtotalparts", filename: "qqfilename"}}, resume: {enabled: false, id: null, cookiesExpireIn: 7, paramNames: {resuming: "qqresume"}}, formatFileName: function (e) { + if (e.length > 33) { + e = e.slice(0, 19) + "..." + e.slice(-14) + } + return e + }, text: {sizeSymbols: ["kB", "MB", "GB", "TB", "PB", "EB"]}}; + qq.extend(this._options, e, true); + this._wrapCallbacks(); + this._disposeSupport = new qq.DisposeSupport; + this._filesInProgress = []; + this._storedFileIds = []; + this._autoRetries = []; + this._retryTimeouts = []; + this._preventRetries = []; + this._paramsStore = this._createParamsStore(); + this._endpointStore = this._createEndpointStore(); + this._handler = this._createUploadHandler(); + if (this._options.button) { + this._button = this._createUploadButton(this._options.button) + } + this._preventLeaveInProgress() +}; +qq.FineUploaderBasic.prototype = {log: function (e, t) { + if (this._options.debug && (!t || t === "info")) { + qq.log("[FineUploader] " + e) + } else if (t && t !== "info") { + qq.log("[FineUploader] " + e, t) + } +}, setParams: function (e, t) { + if (t == null) { + this._options.request.params = e + } else { + this._paramsStore.setParams(e, t) + } +}, setEndpoint: function (e, t) { + if (t == null) { + this._options.request.endpoint = e + } else { + this._endpointStore.setEndpoint(e, t) + } +}, getInProgress: function () { + return this._filesInProgress.length +}, uploadStoredFiles: function () { + "use strict"; + var e; + while (this._storedFileIds.length) { + e = this._storedFileIds.shift(); + this._filesInProgress.push(e); + this._handler.upload(e) + } +}, clearStoredFiles: function () { + this._storedFileIds = [] +}, retry: function (e) { + if (this._onBeforeManualRetry(e)) { + this._handler.retry(e); + return true + } else { + return false + } +}, cancel: function (e) { + this._handler.cancel(e) +}, reset: function () { + this.log("Resetting uploader..."); + this._handler.reset(); + this._filesInProgress = []; + this._storedFileIds = []; + this._autoRetries = []; + this._retryTimeouts = []; + this._preventRetries = []; + this._button.reset(); + this._paramsStore.reset(); + this._endpointStore.reset() +}, addFiles: function (e) { + var t = this, n = [], r, i; + if (e) { + if (!window.FileList || !(e instanceof FileList)) { + e = [].concat(e) + } + for (r = 0; r < e.length; r += 1) { + i = e[r]; + if (qq.isFileOrInput(i)) { + n.push(i) + } else { + t.log(i + " is not a File or INPUT element! Ignoring!", "warn") + } + } + this.log("Processing " + n.length + " files or inputs..."); + this._uploadFileList(n) + } +}, getUuid: function (e) { + return this._handler.getUuid(e) +}, getResumableFilesData: function () { + return this._handler.getResumableFilesData() +}, getSize: function (e) { + return this._handler.getSize(e) +}, getFile: function (e) { + return this._handler.getFile(e) +}, _createUploadButton: function (e) { + var t = this; + var n = new qq.UploadButton({element: e, multiple: this._options.multiple && qq.isXhrUploadSupported(), acceptFiles: this._options.validation.acceptFiles, onChange: function (e) { + t._onInputChange(e) + }, hoverClass: this._options.classes.buttonHover, focusClass: this._options.classes.buttonFocus}); + this._disposeSupport.addDisposer(function () { + n.dispose() + }); + return n +}, _createUploadHandler: function () { + var e = this; + return new qq.UploadHandler({debug: this._options.debug, forceMultipart: this._options.request.forceMultipart, maxConnections: this._options.maxConnections, customHeaders: this._options.request.customHeaders, inputName: this._options.request.inputName, uuidParamName: this._options.request.uuidName, totalFileSizeParamName: this._options.request.totalFileSizeName, demoMode: this._options.demoMode, paramsInBody: this._options.request.paramsInBody, paramsStore: this._paramsStore, endpointStore: this._endpointStore, chunking: this._options.chunking, resume: this._options.resume, log: function (t, n) { + e.log(t, n) + }, onProgress: function (t, n, r, i) { + e._onProgress(t, n, r, i); + e._options.callbacks.onProgress(t, n, r, i) + }, onComplete: function (t, n, r, i) { + e._onComplete(t, n, r, i); + e._options.callbacks.onComplete(t, n, r) + }, onCancel: function (t, n) { + e._onCancel(t, n); + e._options.callbacks.onCancel(t, n) + }, onUpload: function (t, n) { + e._onUpload(t, n); + e._options.callbacks.onUpload(t, n) + }, onUploadChunk: function (t, n, r) { + e._options.callbacks.onUploadChunk(t, n, r) + }, onResume: function (t, n, r) { + return e._options.callbacks.onResume(t, n, r) + }, onAutoRetry: function (t, n, r, i) { + e._preventRetries[t] = r[e._options.retry.preventRetryResponseProperty]; + if (e._shouldAutoRetry(t, n, r)) { + e._maybeParseAndSendUploadError(t, n, r, i); + e._options.callbacks.onAutoRetry(t, n, e._autoRetries[t] + 1); + e._onBeforeAutoRetry(t, n); + e._retryTimeouts[t] = setTimeout(function () { + e._onAutoRetry(t, n, r) + }, e._options.retry.autoAttemptDelay * 1e3); + return true + } else { + return false + } + }}) +}, _preventLeaveInProgress: function () { + var e = this; + this._disposeSupport.attach(window, "beforeunload", function (t) { + if (!e._filesInProgress.length) { + return + } + var t = t || window.event; + t.returnValue = e._options.messages.onLeave; + return e._options.messages.onLeave + }) +}, _onSubmit: function (e, t) { + if (this._options.autoUpload) { + this._filesInProgress.push(e) + } +}, _onProgress: function (e, t, n, r) { +}, _onComplete: function (e, t, n, r) { + this._removeFromFilesInProgress(e); + this._maybeParseAndSendUploadError(e, t, n, r) +}, _onCancel: function (e, t) { + this._removeFromFilesInProgress(e); + clearTimeout(this._retryTimeouts[e]); + var n = qq.indexOf(this._storedFileIds, e); + if (!this._options.autoUpload && n >= 0) { + this._storedFileIds.splice(n, 1) + } +}, _removeFromFilesInProgress: function (e) { + var t = qq.indexOf(this._filesInProgress, e); + if (t >= 0) { + this._filesInProgress.splice(t, 1) + } +}, _onUpload: function (e, t) { +}, _onInputChange: function (e) { + if (qq.isXhrUploadSupported()) { + this.addFiles(e.files) + } else { + this.addFiles(e) + } + this._button.reset() +}, _onBeforeAutoRetry: function (e, t) { + this.log("Waiting " + this._options.retry.autoAttemptDelay + " seconds before retrying " + t + "...") +}, _onAutoRetry: function (e, t, n) { + this.log("Retrying " + t + "..."); + this._autoRetries[e]++; + this._handler.retry(e) +}, _shouldAutoRetry: function (e, t, n) { + if (!this._preventRetries[e] && this._options.retry.enableAuto) { + if (this._autoRetries[e] === undefined) { + this._autoRetries[e] = 0 + } + return this._autoRetries[e] < this._options.retry.maxAutoAttempts + } + return false +}, _onBeforeManualRetry: function (e) { + if (this._preventRetries[e]) { + this.log("Retries are forbidden for id " + e, "warn"); + return false + } else if (this._handler.isValid(e)) { + var t = this._handler.getName(e); + if (this._options.callbacks.onManualRetry(e, t) === false) { + return false + } + this.log("Retrying upload for '" + t + "' (id: " + e + ")..."); + this._filesInProgress.push(e); + return true + } else { + this.log("'" + e + "' is not a valid file ID", "error"); + return false + } +}, _maybeParseAndSendUploadError: function (e, t, n, r) { + if (!n.success) { + if (r && r.status !== 200 && !n.error) { + this._options.callbacks.onError(e, t, "XHR returned response code " + r.status) + } else { + var i = n.error ? n.error : "Upload failure reason unknown"; + this._options.callbacks.onError(e, t, i) + } + } +}, _uploadFileList: function (e) { + var t, n, r; + t = this._getValidationDescriptors(e); + r = this._options.callbacks.onValidateBatch(t) === false; + if (!r) { + if (e.length > 0) { + for (n = 0; n < e.length; n++) { + if (this._validateFile(e[n])) { + this._uploadFile(e[n]) + } else { + if (this._options.validation.stopOnFirstInvalidFile) { + return + } + } + } + } else { + this._error("noFilesError", "") + } + } +}, _uploadFile: function (e) { + var t = this._handler.add(e); + var n = this._handler.getName(t); + if (this._options.callbacks.onSubmit(t, n) !== false) { + this._onSubmit(t, n); + if (this._options.autoUpload) { + this._handler.upload(t) + } else { + this._storeFileForLater(t) + } + } +}, _storeFileForLater: function (e) { + this._storedFileIds.push(e) +}, _validateFile: function (e) { + var t, n, r; + t = this._getValidationDescriptor(e); + n = t.name; + r = t.size; + if (this._options.callbacks.onValidate(t) === false) { + return false + } + if (!this._isAllowedExtension(n)) { + this._error("typeError", n); + return false + } else if (r === 0) { + this._error("emptyError", n); + return false + } else if (r && this._options.validation.sizeLimit && r > this._options.validation.sizeLimit) { + this._error("sizeError", n); + return false + } else if (r && r < this._options.validation.minSizeLimit) { + this._error("minSizeError", n); + return false + } + return true +}, _error: function (e, t) { + function r(e, t) { + n = n.replace(e, t) + } + + var n = this._options.messages[e]; + var i = this._options.validation.allowedExtensions.join(", ").toLowerCase(); + r("{file}", this._options.formatFileName(t)); + r("{extensions}", i); + r("{sizeLimit}", this._formatSize(this._options.validation.sizeLimit)); + r("{minSizeLimit}", this._formatSize(this._options.validation.minSizeLimit)); + this._options.callbacks.onError(null, t, n); + return n +}, _isAllowedExtension: function (e) { + var t = this._options.validation.allowedExtensions, n = false; + if (!t.length) { + return true + } + qq.each(t, function (t, r) { + var i = new RegExp("\\." + r + "$", "i"); + if (e.match(i) != null) { + n = true; + return false + } + }); + return n +}, _formatSize: function (e) { + var t = -1; + do { + e = e / 1024; + t++ + } while (e > 99); + return Math.max(e, .1).toFixed(1) + this._options.text.sizeSymbols[t] +}, _wrapCallbacks: function () { + var e, t; + e = this; + t = function (t, n, r) { + try { + return n.apply(e, r) + } catch (i) { + e.log("Caught exception in '" + t + "' callback - " + i.message, "error") + } + }; + for (var n in this._options.callbacks) { + (function () { + var r, i; + r = n; + i = e._options.callbacks[r]; + e._options.callbacks[r] = function () { + return t(r, i, arguments) + } + })() + } +}, _parseFileName: function (e) { + var t; + if (e.value) { + t = e.value.replace(/.*(\/|\\)/, "") + } else { + t = e.fileName !== null && e.fileName !== undefined ? e.fileName : e.name + } + return t +}, _parseFileSize: function (e) { + var t; + if (!e.value) { + t = e.fileSize !== null && e.fileSize !== undefined ? e.fileSize : e.size + } + return t +}, _getValidationDescriptor: function (e) { + var t, n, r; + r = {}; + t = this._parseFileName(e); + n = this._parseFileSize(e); + r.name = t; + if (n) { + r.size = n + } + return r +}, _getValidationDescriptors: function (e) { + var t = this, n = []; + qq.each(e, function (e, r) { + n.push(t._getValidationDescriptor(r)) + }); + return n +}, _createParamsStore: function () { + var e = {}, t = this; + return{setParams: function (t, n) { + var r = {}; + qq.extend(r, t); + e[n] = r + }, getParams: function (n) { + var r = {}; + if (n != null && e[n]) { + qq.extend(r, e[n]) + } else { + qq.extend(r, t._options.request.params) + } + return r + }, remove: function (t) { + return delete e[t] + }, reset: function () { + e = {} + }} +}, _createEndpointStore: function () { + var e = {}, t = this; + return{setEndpoint: function (t, n) { + e[n] = t + }, getEndpoint: function (n) { + if (n != null && e[n]) { + return e[n] + } + return t._options.request.endpoint + }, remove: function (t) { + return delete e[t] + }, reset: function () { + e = {} + }} +}}; +qq.DragAndDrop = function (e) { + "use strict"; + function a() { + if (s === o && !r) { + t.callbacks.log("Grabbed " + i.length + " files after tree traversal."); + n.dropDisabled(false); + t.callbacks.dropProcessing(false, i) + } + } + + function f(e) { + i.push(e); + o += 1; + a() + } + + function l(e) { + var t, n; + s += 1; + if (e.isFile) { + e.file(function (e) { + f(e) + }) + } else if (e.isDirectory) { + r = true; + t = e.createReader(); + t.readEntries(function (e) { + o += 1; + for (n = 0; n < e.length; n += 1) { + l(e[n]) + } + r = false; + if (!e.length) { + a() + } + }) + } + } + + function c(e) { + var r, u, f; + t.callbacks.dropProcessing(true); + n.dropDisabled(true); + if (e.files.length > 1 && !t.multiple) { + t.callbacks.dropProcessing(false); + t.callbacks.error("tooManyFilesError", ""); + n.dropDisabled(false) + } else { + i = []; + s = 0; + o = 0; + if (qq.isFolderDropSupported(e)) { + u = e.items; + for (r = 0; r < u.length; r += 1) { + f = u[r].webkitGetAsEntry(); + if (f) { + if (f.isFile) { + i.push(u[r].getAsFile()); + if (r === u.length - 1) { + a() + } + } else { + l(f) + } + } + } + } else { + t.callbacks.dropProcessing(false, e.files); + n.dropDisabled(false) + } + } + } + + function h(e) { + n = new qq.UploadDropZone({element: e, onEnter: function (n) { + qq(e).addClass(t.classes.dropActive); + n.stopPropagation() + }, onLeaveNotDescendants: function (n) { + qq(e).removeClass(t.classes.dropActive) + }, onDrop: function (n) { + if (t.hideDropzones) { + qq(e).hide() + } + qq(e).removeClass(t.classes.dropActive); + c(n.dataTransfer) + }}); + u.addDisposer(function () { + n.dispose() + }); + if (t.hideDropzones) { + qq(e).hide() + } + } + + function p(e) { + var t; + qq.each(e.dataTransfer.types, function (e, n) { + if (n === "Files") { + t = true; + return false + } + }); + return t + } + + function d() { + if (t.dropArea) { + t.extraDropzones.push(t.dropArea) + } + var e, r = t.extraDropzones; + for (e = 0; e < r.length; e += 1) { + h(r[e]) + } + if (t.dropArea && (!qq.ie() || qq.ie10())) { + u.attach(document, "dragenter", function (i) { + if (!n.dropDisabled() && p(i)) { + if (qq(t.dropArea).hasClass(t.classes.dropDisabled)) { + return + } + t.dropArea.style.display = "block"; + for (e = 0; e < r.length; e += 1) { + r[e].style.display = "block" + } + } + }) + } + u.attach(document, "dragleave", function (n) { + if (t.hideDropzones && qq.FineUploader.prototype._leaving_document_out(n)) { + for (e = 0; e < r.length; e += 1) { + qq(r[e]).hide() + } + } + }); + u.attach(document, "drop", function (n) { + if (t.hideDropzones) { + for (e = 0; e < r.length; e += 1) { + qq(r[e]).hide() + } + } + n.preventDefault() + }) + } + + var t, n, r, i = [], s = 0, o = 0, u = new qq.DisposeSupport; + t = {dropArea: null, extraDropzones: [], hideDropzones: true, multiple: true, classes: {dropActive: null}, callbacks: {dropProcessing: function (e, t) { + }, error: function (e, t) { + }, log: function (e, t) { + }}}; + qq.extend(t, e); + return{setup: function () { + d() + }, setupExtraDropzone: function (e) { + t.extraDropzones.push(e); + h(e) + }, removeExtraDropzone: function (e) { + var n, r = t.extraDropzones; + for (n in r) { + if (r[n] === e) { + return r.splice(n, 1) + } + } + }, dispose: function () { + u.dispose(); + n.dispose() + }} +}; +qq.UploadDropZone = function (e) { + "use strict"; + function o() { + return qq.safari() || qq.firefox() && qq.windows() + } + + function u(e) { + if (!i) { + if (o) { + s.attach(document, "dragover", function (e) { + e.preventDefault() + }) + } else { + s.attach(document, "dragover", function (e) { + if (e.dataTransfer) { + e.dataTransfer.dropEffect = "none"; + e.preventDefault() + } + }) + } + i = true + } + } + + function a(e) { + if (qq.ie() && !qq.ie10()) { + return false + } + var t, n = e.dataTransfer, r = qq.safari(); + t = qq.ie10() ? true : n.effectAllowed !== "none"; + return n && t && (n.files || !r && n.types.contains && n.types.contains("Files")) + } + + function f(e) { + if (e !== undefined) { + r = e + } + return r + } + + function l() { + s.attach(n, "dragover", function (e) { + if (!a(e)) { + return + } + var t = qq.ie() ? null : e.dataTransfer.effectAllowed; + if (t === "move" || t === "linkMove") { + e.dataTransfer.dropEffect = "move" + } else { + e.dataTransfer.dropEffect = "copy" + } + e.stopPropagation(); + e.preventDefault() + }); + s.attach(n, "dragenter", function (e) { + if (!f()) { + if (!a(e)) { + return + } + t.onEnter(e) + } + }); + s.attach(n, "dragleave", function (e) { + if (!a(e)) { + return + } + t.onLeave(e); + var n = document.elementFromPoint(e.clientX, e.clientY); + if (qq(this).contains(n)) { + return + } + t.onLeaveNotDescendants(e) + }); + s.attach(n, "drop", function (e) { + if (!f()) { + if (!a(e)) { + return + } + e.preventDefault(); + t.onDrop(e) + } + }) + } + + var t, n, r, i, s = new qq.DisposeSupport; + t = {element: null, onEnter: function (e) { + }, onLeave: function (e) { + }, onLeaveNotDescendants: function (e) { + }, onDrop: function (e) { + }}; + qq.extend(t, e); + n = t.element; + u(); + l(); + return{dropDisabled: function (e) { + return f(e) + }, dispose: function () { + s.dispose() + }} +}; +qq.FineUploader = function (e) { + qq.FineUploaderBasic.apply(this, arguments); + qq.extend(this._options, {element: null, listElement: null, dragAndDrop: {extraDropzones: [], hideDropzones: true, disableDefaultDropzone: false}, text: {uploadButton: "Upload a file", cancelButton: "Cancel", retryButton: "Retry", failUpload: "Upload failed", dragZone: "Drop files here to upload", dropProcessing: "Processing dropped files...", formatProgress: "{percent}% of {total_size}", waitingForResponse: "Processing..."}, template: '
      ' + (!this._options.dragAndDrop || !this._options.dragAndDrop.disableDefaultDropzone ? '
      {dragZoneText}
      ' : "") + (!this._options.button ? '
      {uploadButtonText}
      ' : "") + '{dropProcessingText}' + (!this._options.listElement ? '
        ' : "") + "
        ", fileTemplate: "
      • " + '
        ' + '' + '' + '' + '' + '{cancelButtonText}' + '{retryButtonText}' + '{statusText}' + "
      • ", classes: {button: "qq-upload-button", drop: "qq-upload-drop-area", dropActive: "qq-upload-drop-area-active", dropDisabled: "qq-upload-drop-area-disabled", list: "qq-upload-list", progressBar: "qq-progress-bar", file: "qq-upload-file", spinner: "qq-upload-spinner", finished: "qq-upload-finished", retrying: "qq-upload-retrying", retryable: "qq-upload-retryable", size: "qq-upload-size", cancel: "qq-upload-cancel", retry: "qq-upload-retry", statusText: "qq-upload-status-text", success: "qq-upload-success", fail: "qq-upload-fail", successIcon: null, failIcon: null, dropProcessing: "qq-drop-processing", dropProcessingSpinner: "qq-drop-processing-spinner"}, failedUploadTextDisplay: {mode: "default", maxChars: 50, responseProperty: "error", enableTooltip: true}, messages: {tooManyFilesError: "You may only drop one file"}, retry: {showAutoRetryNote: true, autoRetryNote: "Retrying {retryNum}/{maxAuto}...", showButton: false}, showMessage: function (e) { + setTimeout(function () { + alert(e) + }, 0) + }}, true); + qq.extend(this._options, e, true); + this._wrapCallbacks(); + this._options.template = this._options.template.replace(/\{dragZoneText\}/g, this._options.text.dragZone); + this._options.template = this._options.template.replace(/\{uploadButtonText\}/g, this._options.text.uploadButton); + this._options.template = this._options.template.replace(/\{dropProcessingText\}/g, this._options.text.dropProcessing); + this._options.fileTemplate = this._options.fileTemplate.replace(/\{cancelButtonText\}/g, this._options.text.cancelButton); + this._options.fileTemplate = this._options.fileTemplate.replace(/\{retryButtonText\}/g, this._options.text.retryButton); + this._options.fileTemplate = this._options.fileTemplate.replace(/\{statusText\}/g, ""); + this._element = this._options.element; + this._element.innerHTML = this._options.template; + this._listElement = this._options.listElement || this._find(this._element, "list"); + this._classes = this._options.classes; + if (!this._button) { + this._button = this._createUploadButton(this._find(this._element, "button")) + } + this._bindCancelAndRetryEvents(); + this._dnd = this._setupDragAndDrop() +}; +qq.extend(qq.FineUploader.prototype, qq.FineUploaderBasic.prototype); +qq.extend(qq.FineUploader.prototype, {clearStoredFiles: function () { + qq.FineUploaderBasic.prototype.clearStoredFiles.apply(this, arguments); + this._listElement.innerHTML = "" +}, addExtraDropzone: function (e) { + this._dnd.setupExtraDropzone(e) +}, removeExtraDropzone: function (e) { + return this._dnd.removeExtraDropzone(e) +}, getItemByFileId: function (e) { + var t = this._listElement.firstChild; + while (t) { + if (t.qqFileId == e)return t; + t = t.nextSibling + } +}, cancel: function (e) { + qq.FineUploaderBasic.prototype.cancel.apply(this, arguments); + var t = this.getItemByFileId(e); + qq(t).remove() +}, reset: function () { + qq.FineUploaderBasic.prototype.reset.apply(this, arguments); + this._element.innerHTML = this._options.template; + this._listElement = this._options.listElement || this._find(this._element, "list"); + if (!this._options.button) { + this._button = this._createUploadButton(this._find(this._element, "button")) + } + this._bindCancelAndRetryEvents(); + this._dnd.dispose(); + this._dnd = this._setupDragAndDrop() +}, _setupDragAndDrop: function () { + var e = this, t = this._find(this._element, "dropProcessing"), n, r, i; + r = function (e) { + e.preventDefault() + }; + if (!this._options.dragAndDrop.disableDefaultDropzone) { + i = this._find(this._options.element, "drop") + } + n = new qq.DragAndDrop({dropArea: i, extraDropzones: this._options.dragAndDrop.extraDropzones, hideDropzones: this._options.dragAndDrop.hideDropzones, multiple: this._options.multiple, classes: {dropActive: this._options.classes.dropActive}, callbacks: {dropProcessing: function (n, i) { + var s = e._button.getInput(); + if (n) { + qq(t).css({display: "block"}); + qq(s).attach("click", r) + } else { + qq(t).hide(); + qq(s).detach("click", r) + } + if (i) { + e.addFiles(i) + } + }, error: function (t, n) { + e._error(t, n) + }, log: function (t, n) { + e.log(t, n) + }}}); + n.setup(); + return n +}, _leaving_document_out: function (e) { + return(qq.chrome() || qq.safari() && qq.windows()) && e.clientX == 0 && e.clientY == 0 || qq.firefox() && !e.relatedTarget +}, _storeFileForLater: function (e) { + qq.FineUploaderBasic.prototype._storeFileForLater.apply(this, arguments); + var t = this.getItemByFileId(e); + qq(this._find(t, "spinner")).hide() +}, _find: function (e, t) { + var n = qq(e).getByClass(this._options.classes[t])[0]; + if (!n) { + throw new Error("element not found " + t) + } + return n +}, _onSubmit: function (e, t) { + qq.FineUploaderBasic.prototype._onSubmit.apply(this, arguments); + this._addToList(e, t) +}, _onProgress: function (e, t, n, r) { + qq.FineUploaderBasic.prototype._onProgress.apply(this, arguments); + var i, s, o, u, a, f; + i = this.getItemByFileId(e); + s = this._find(i, "progressBar"); + u = Math.round(n / r * 100); + if (n === r) { + a = this._find(i, "cancel"); + qq(a).hide(); + qq(s).hide(); + qq(this._find(i, "statusText")).setText(this._options.text.waitingForResponse); + o = this._formatSize(r) + } else { + o = this._formatProgress(n, r); + qq(s).css({display: "block"}) + } + qq(s).css({width: u + "%"}); + f = this._find(i, "size"); + qq(f).css({display: "inline"}); + qq(f).setText(o) +}, _onComplete: function (e, t, n, r) { + qq.FineUploaderBasic.prototype._onComplete.apply(this, arguments); + var i = this.getItemByFileId(e); + qq(this._find(i, "statusText")).clearText(); + qq(i).removeClass(this._classes.retrying); + qq(this._find(i, "progressBar")).hide(); + if (!this._options.disableCancelForFormUploads || qq.isXhrUploadSupported()) { + qq(this._find(i, "cancel")).hide() + } + qq(this._find(i, "spinner")).hide(); + if (n.success) { + qq(i).addClass(this._classes.success); + if (this._classes.successIcon) { + this._find(i, "finished").style.display = "inline-block"; + qq(i).addClass(this._classes.successIcon) + } + } else { + qq(i).addClass(this._classes.fail); + if (this._classes.failIcon) { + this._find(i, "finished").style.display = "inline-block"; + qq(i).addClass(this._classes.failIcon) + } + if (this._options.retry.showButton && !this._preventRetries[e]) { + qq(i).addClass(this._classes.retryable) + } + this._controlFailureTextDisplay(i, n) + } +}, _onUpload: function (e, t) { + qq.FineUploaderBasic.prototype._onUpload.apply(this, arguments); + var n = this.getItemByFileId(e); + this._showSpinner(n) +}, _onBeforeAutoRetry: function (e) { + var t, n, r, i, s, o, u; + qq.FineUploaderBasic.prototype._onBeforeAutoRetry.apply(this, arguments); + t = this.getItemByFileId(e); + n = this._find(t, "progressBar"); + this._showCancelLink(t); + n.style.width = 0; + qq(n).hide(); + if (this._options.retry.showAutoRetryNote) { + i = this._find(t, "statusText"); + s = this._autoRetries[e] + 1; + o = this._options.retry.maxAutoAttempts; + u = this._options.retry.autoRetryNote.replace(/\{retryNum\}/g, s); + u = u.replace(/\{maxAuto\}/g, o); + qq(i).setText(u); + if (s === 1) { + qq(t).addClass(this._classes.retrying) + } + } +}, _onBeforeManualRetry: function (e) { + if (qq.FineUploaderBasic.prototype._onBeforeManualRetry.apply(this, arguments)) { + var t = this.getItemByFileId(e); + this._find(t, "progressBar").style.width = 0; + qq(t).removeClass(this._classes.fail); + qq(this._find(t, "statusText")).clearText(); + this._showSpinner(t); + this._showCancelLink(t); + return true + } + return false +}, _addToList: function (e, t) { + var n = qq.toElement(this._options.fileTemplate); + if (this._options.disableCancelForFormUploads && !qq.isXhrUploadSupported()) { + var r = this._find(n, "cancel"); + qq(r).remove() + } + n.qqFileId = e; + var i = this._find(n, "file"); + qq(i).setText(this._options.formatFileName(t)); + qq(this._find(n, "size")).hide(); + if (!this._options.multiple)this._clearList(); + this._listElement.appendChild(n) +}, _clearList: function () { + this._listElement.innerHTML = ""; + this.clearStoredFiles() +}, _bindCancelAndRetryEvents: function () { + var e = this, t = this._listElement; + this._disposeSupport.attach(t, "click", function (t) { + t = t || window.event; + var n = t.target || t.srcElement; + if (qq(n).hasClass(e._classes.cancel) || qq(n).hasClass(e._classes.retry)) { + qq.preventDefault(t); + var r = n.parentNode; + while (r.qqFileId == undefined) { + r = n = n.parentNode + } + if (qq(n).hasClass(e._classes.cancel)) { + e.cancel(r.qqFileId) + } else { + qq(r).removeClass(e._classes.retryable); + e.retry(r.qqFileId) + } + } + }) +}, _formatProgress: function (e, t) { + function r(e, t) { + n = n.replace(e, t) + } + + var n = this._options.text.formatProgress; + r("{percent}", Math.round(e / t * 100)); + r("{total_size}", this._formatSize(t)); + return n +}, _controlFailureTextDisplay: function (e, t) { + var n, r, i, s, o; + n = this._options.failedUploadTextDisplay.mode; + r = this._options.failedUploadTextDisplay.maxChars; + i = this._options.failedUploadTextDisplay.responseProperty; + if (n === "custom") { + s = t[i]; + if (s) { + if (s.length > r) { + o = s.substring(0, r) + "..." + } + } else { + s = this._options.text.failUpload; + this.log("'" + i + "' is not a valid property on the server response.", "warn") + } + qq(this._find(e, "statusText")).setText(o || s); + if (this._options.failedUploadTextDisplay.enableTooltip) { + this._showTooltip(e, s) + } + } else if (n === "default") { + qq(this._find(e, "statusText")).setText(this._options.text.failUpload) + } else if (n !== "none") { + this.log("failedUploadTextDisplay.mode value of '" + n + "' is not valid", "warn") + } +}, _showTooltip: function (e, t) { + e.title = t +}, _showSpinner: function (e) { + var t = this._find(e, "spinner"); + t.style.display = "inline-block" +}, _showCancelLink: function (e) { + if (!this._options.disableCancelForFormUploads || qq.isXhrUploadSupported()) { + var t = this._find(e, "cancel"); + t.style.display = "inline" + } +}, _error: function (e, t) { + var n = qq.FineUploaderBasic.prototype._error.apply(this, arguments); + this._options.showMessage(n) +}}); +(function (e) { + "use strict"; + var t, n, r, i, s, o, u, a, f, l; + o = ["uploaderType"]; + r = function (e) { + if (e) { + var r = a(e); + u(r); + if (s("uploaderType") === "basic") { + t(new qq.FineUploaderBasic(r)) + } else { + t(new qq.FineUploader(r)) + } + } + return n + }; + i = function (e, t) { + var r = n.data("fineuploader"); + if (t) { + if (r === undefined) { + r = {} + } + r[e] = t; + n.data("fineuploader", r) + } else { + if (r === undefined) { + return null + } + return r[e] + } + }; + t = function (e) { + return i("uploader", e) + }; + s = function (e, t) { + return i(e, t) + }; + u = function (t) { + var r = t.callbacks = {}; + e.each((new qq.FineUploaderBasic)._options.callbacks, function (e, t) { + var i, s; + i = /^on(\w+)/.exec(e)[1]; + i = i.substring(0, 1).toLowerCase() + i.substring(1); + s = n; + r[e] = function () { + var e = Array.prototype.slice.call(arguments); + return s.triggerHandler(i, e) + } + }) + }; + a = function (t, r) { + var i, u; + if (r === undefined) { + if (t.uploaderType !== "basic") { + i = {element: n[0]} + } else { + i = {} + } + } else { + i = r + } + e.each(t, function (t, n) { + if (e.inArray(t, o) >= 0) { + s(t, n) + } else if (n instanceof e) { + i[t] = n[0] + } else if (e.isPlainObject(n)) { + i[t] = {}; + a(n, i[t]) + } else if (e.isArray(n)) { + u = []; + e.each(n, function (t, n) { + if (n instanceof e) { + e.merge(u, n) + } else { + u.push(n) + } + }); + i[t] = u + } else { + i[t] = n + } + }); + if (r === undefined) { + return i + } + }; + f = function (n) { + return e.type(n) === "string" && !n.match(/^_/) && t()[n] !== undefined + }; + l = function (e) { + var n = [], r = Array.prototype.slice.call(arguments, 1); + a(r, n); + return t()[e].apply(t(), n) + }; + e.fn.fineUploader = function (i) { + var s = this, o = arguments, u = []; + this.each(function (a, c) { + n = e(c); + if (t() && f(i)) { + u.push(l.apply(s, o)); + if (s.length === 1) { + return false + } + } else if (typeof i === "object" || !i) { + r.apply(s, o) + } else { + e.error("Method " + i + " does not exist on jQuery.fineUploader") + } + }); + if (u.length === 1) { + return u[0] + } else if (u.length > 1) { + return u + } + return this + } +})(jQuery) \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/form/WhActiveForm.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/form/WhActiveForm.php new file mode 100644 index 0000000..85efec7 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/form/WhActiveForm.php @@ -0,0 +1,167 @@ + + * @copyright Copyright © 2amigos.us 2013- + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @package YiiWheels.widgets + * @uses YiiStrap.widgets.form + * @uses YiiWheels.helpers.WhHtml + */ + +Yii::import('bootstrap.widgets.TbActiveForm'); +Yii::import('yiiwheels.helpers.WhHtml'); + +class WhActiveForm extends TbActiveForm +{ + /** + * Renders a datepicker field + * @param $model + * @param $attribute + * @param array $htmlOptions + * @return string + */ + public function datePickerRow($model, $attribute, $htmlOptions = array()) + { + return $this->row(WhHtml::INPUT_DATEPICKER, $model, $attribute, array(), $htmlOptions); + } + + /** + * Renders a timepicker field + * @param $model + * @param $attribute + * @param array $htmlOptions + * @return string + */ + public function timePickerRow($model, $attribute, $htmlOptions = array()) + { + return $this->row(WhHtml::INPUT_TIMEPICKER, $model, $attribute, array(), $htmlOptions); + } + + /** + * Renders a typeahead field + * @param $model + * @param $attribute + * @param array $htmlOptions + * @return string + */ + public function typeAheadRow($model, $attribute, $htmlOptions = array()) + { + return $this->row(WhHtml::INPUT_TYPEAHEAD, $model, $attribute, array(), $htmlOptions); + } + + /** + * Renders a typeahead field + * @param $model + * @param $attribute + * @param array $htmlOptions + * @return string + */ + public function select2Row($model, $attribute, $htmlOptions = array()) + { + return $this->row(WhHtml::INPUT_SELECT2, $model, $attribute, array(), $htmlOptions); + } + + /** + * Renders a multiselect field + * @param $model + * @param $attribute + * @param array $htmlOptions + * @return string + */ + public function multiSelectRow($model, $attribute, $htmlOptions = array()) + { + return $this->row(WhHtml::INPUT_MULTISELECT, $model, $attribute, array(), $htmlOptions); + } + + /** + * Renders a maskmoney field + * @param $model + * @param $attribute + * @param array $htmlOptions + * @return string + */ + public function maskMoneyRow($model, $attribute, $htmlOptions = array()) + { + return $this->row(WhHtml::INPUT_MASKMONEY, $model, $attribute, array(), $htmlOptions); + } + + /** + * Renders a redactor wyiwyg field + * @param $model + * @param $attribute + * @param array $htmlOptions + * @return string + */ + public function redactorJsRow($model, $attribute, $htmlOptions = array()) + { + return $this->row(WhHtml::INPUT_REDACTOR, $model, $attribute, array(), $htmlOptions); + } + + /** + * Helper method to display different input types for the different complain bootstrap forms wrapped with their + * labels, help and error messages. This method is a replacement of the old 'typeRow' methods from Yii-Bootstrap + * extension. Example: + *
        +	 *     $form->row(WhHtml::INPUT_TEXT, $model, 'attribute', array('style'=>'width:125px'));
        +	 *    $form->row(WhHtml::INPUT_DROPDOWN, $model, 'attribute', array('a'=>'A','b'=>'B'), array());
        +	 * 
        + * @param $type + * @param $model + * @param $attribute + * @param $data + * @param array $htmlOptions + * @return string + * @throws CException + */ + public function row($type, $model, $attribute, $data = array(), $htmlOptions = array()) + { + if (!in_array($type, WhHtml::validInputs())) + throw new CException(Yii::t('tb', 'Unrecognized input type')); + + $labelOptions = WhHtml::popOption('labelOptions', $htmlOptions, array()); + $errorOptions = WhHtml::popOption('errorOptions', $htmlOptions, array()); + $containerOptions = WhHtml::popOption('containerOptions', $htmlOptions, array()); + + $labelOptions = WhHtml::defaultOption('formType', $this->type, $labelOptions); + + ob_start(); + + // make sure it holds the class control-label + if ($this->type === WhHtml::FORM_HORIZONTAL) + echo CHtml::openTag('div', WhHtml::addClassName('control-group', $containerOptions)); + + // form's inline do not render labels and radio|checkbox input types render label's differently + if ($this->type !== WhHtml::FORM_INLINE + && !preg_match('/radio|checkbox/i', $type) + && WhHtml::popOption('label', $htmlOptions, true) + ) + echo CHtml::activeLabel($model, $attribute, $labelOptions); + elseif (preg_match('/radio|checkbox/i', $type)) + $htmlOptions['labelOptions'] = $labelOptions; + + if (WhHtml::popOption('block', $htmlOptions, false)) + $htmlOptions = WhHtml::addClassName('input-block-level', $htmlOptions); + + $params = in_array($type, WhHtml::$dataInputs) + ? array($model, $attribute, $data, $htmlOptions) + : array($model, $attribute, $htmlOptions); + + $errorSpan = $this->error($model, $attribute, $errorOptions); + + echo $this->wrapControl(call_user_func_array('WhHtml::active' . ucfirst($type), $params), $errorSpan); /* since PHP 5.3 */ + + if ($this->type == WhHtml::FORM_VERTICAL && WhHtml::popOption('error', $htmlOptions, true)) + echo $errorSpan; + + if ($this->type == WhHtml::FORM_HORIZONTAL) + echo '
        '; + + return ob_get_clean(); + + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/google/WhVisualizationChart.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/google/WhVisualizationChart.php new file mode 100644 index 0000000..066bcaf --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/google/WhVisualizationChart.php @@ -0,0 +1,90 @@ + + * @copyright Copyright © 2amigos.us 2013- + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @package YiiWheels.widgets.google + * @uses YiiWheels.helpers.WhHtml + */ +Yii::import('yiiwheels.helpers.WhHtml'); + +class WhVisualizationChart extends CWidget +{ + /** + * @var string $containerId the container Id to render the visualization to + */ + public $containerId; + + /** + * @var string $visualization the type of visualization -ie PieChart + * @see https://google-developers.appspot.com/chart/interactive/docs/gallery + */ + public $visualization; + + /** + * @var array $data the data to configure visualization + * @see https://google-developers.appspot.com/chart/interactive/docs/datatables_dataviews#arraytodatatable + */ + public $data = array(); + + /** + * @var array $options additional configuration options + * @see https://google-developers.appspot.com/chart/interactive/docs/customizing_charts + */ + public $options = array(); + + /** + * @var array $htmlOption the HTML tag attributes configuration + */ + public $htmlOptions = array(); + + /** + * Widget's run method + */ + public function run() + { + $id = $this->getId(); + $this->htmlOptions['id'] = $id; + // if no container is set, it will create one + if ($this->containerId == null) { + $this->containerId = 'div-chart' . $id; + echo '
        htmlOptions) . '>
        '; + } + $this->registerClientScript(); + } + + /** + * Registers required scripts + */ + public function registerClientScript() + { + $id = $this->getId(); + $jsData = CJavaScript::jsonEncode($this->data); + $jsOptions = CJavaScript::jsonEncode($this->options); + + $script = ' + google.setOnLoadCallback(drawChart' . $id . '); + var ' . $id . '=null; + function drawChart' . $id . '() { + var data = google.visualization.arrayToDataTable(' . $jsData . '); + + var options = ' . $jsOptions . '; + + ' . $id . ' = new google.visualization.' . $this->visualization . '(document.getElementById("' . $this->containerId . '")); + ' . $id . '.draw(data, options); + }'; + + /** @var $cs CClientScript */ + $cs = Yii::app()->getClientScript(); + $cs->registerScriptFile('https://www.google.com/jsapi'); + $cs->registerScript( + __CLASS__ . '#' . $id, + 'google.load("visualization", "1", {packages:["corechart"]});', + CClientScript::POS_HEAD + ); + $cs->registerScript($id, $script, CClientScript::POS_HEAD); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/grid/WhRelationalColumn.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/grid/WhRelationalColumn.php new file mode 100644 index 0000000..99100b0 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/grid/WhRelationalColumn.php @@ -0,0 +1,211 @@ + + * @copyright Copyright © 2amigos.us 2013- + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @package YiiWheels.widgets.fileupload + * @uses Yiistrap.widgets.TbDataColumn + */ +Yii::import('bootstrap.widgets.TbDataColumn'); + +class WhRelationalColumn extends TbDataColumn +{ + /** + * @var string $url the route to call via AJAX to get the data from + */ + public $url; + + /** + * @var string $cssClass the class name that will wrap up the cell content. + * Important Note: this class will be used as the trigger for the AJAX call, so make sure is unique for the + * column. + */ + public $cssClass = 'wh-relational-column'; + + /** + * @var bool $cacheData if set to true, there won't be more than one AJAX request. If set to false, the widget will + * continuously make AJAX requests. This is useful if the data could vary. If the data doesn't change then is better + * to set it to true. Defaults to true. + */ + public $cacheData = true; + + /** + * @var string a javascript function that will be invoked if an AJAX call occurs. + * + * The function signature is function(tr, rowid, data) + *
          + *
        • tr is the newly created TR HTML object that will display the returned server data.
        • + *
        • rowid the model id of the row.
        • + *
        • data is the data returned by the server that is already displayed on the row.
        • + *
        + * Note: This handler is not called for JSONP requests. + * + * Example (add in a call to TbRelationalColumn): + *
        +     *  ...
        +     *  'afterAjaxUpdate'=>'js:function(tr,rowid, data){ console.log(rowid); }',
        +     *  ...
        +     * 
        + */ + public $afterAjaxUpdate; + + /** + * @var string $ajaxErrorMessage the message that is displayed on the newly created row in case there is an AJAX + * error. + */ + public $ajaxErrorMessage = 'Error'; + + /** + * widget initialization + */ + public function init() + { + parent::init(); + + if (empty($this->url)) + $this->url = Yii::app()->getRequest()->requestUri; + + $this->registerClientScript(); + } + + /** + * Overrides CDataColumn renderDataCell in order to wrap up its content with the object that will be used as a + * trigger. + * Important: Making use of links as a content for this of column is an error. + * @param int $row + */ + public function renderDataCell($row) + { + $data = $this->grid->dataProvider->data[$row]; + $options = $this->htmlOptions; + if ($this->cssClassExpression !== null) { + $class = $this->evaluateExpression($this->cssClassExpression, array('row' => $row, 'data' => $data)); + if (isset($options['class'])) + $options['class'] .= ' ' . $class; + else + $options['class'] = $class; + } + echo CHtml::openTag('td', $options); + echo CHtml::openTag('span', array('class' => $this->cssClass, 'data-rowid' => $this->getPrimaryKey($data))); + $this->renderDataCellContent($row, $data); + echo ''; + echo ''; + } + + /** + * Helper function to return the primary key of the $data + * * IMPORTANT: composite keys on CActiveDataProviders will return the keys joined by comma + * @param CActiveRecord $data + * @return null|string + */ + protected function getPrimaryKey($data) + { + if ($this->grid->dataProvider instanceof CActiveDataProvider) { + $key = $this->grid->dataProvider->keyAttribute === null ? $data->getPrimaryKey( + ) : $data->{$this->keyAttribute}; + return is_array($key) ? implode(',', $key) : $key; + } + if ($this->grid->dataProvider instanceof CArrayDataProvider || $this->grid->dataProvider instanceof CSqlDataProvider) + return is_object( + $data + ) ? $data->{$this->grid->dataProvider->keyField} : $data[$this->grid->dataProvider->keyField]; + + return null; + } + + /** + * Register script that will handle its behavior + */ + public function registerClientScript() + { + Yii::app()->bootstrap->registerAssetCss('bootstrap-relational.css'); + /** @var $cs CClientScript */ + $cs = Yii::app()->getClientScript(); + if ($this->afterAjaxUpdate !== null) { + if ((!$this->afterAjaxUpdate instanceof CJavaScriptExpression) && strpos( + $this->afterAjaxUpdate, + 'js:' + ) !== 0 + ) + $this->afterAjaxUpdate = new CJavaScriptExpression($this->afterAjaxUpdate); + } else + $this->afterAjaxUpdate = 'js:$.noop'; + + $this->ajaxErrorMessage = CHtml::encode($this->ajaxErrorMessage); + $afterAjaxUpdate = CJavaScript::encode($this->afterAjaxUpdate); + $span = count($this->grid->columns); + $loadingPic = CHtml::image(Yii::app()->yiiwheels->getAssetsUrl() . '/img/loading.gif'); + $cache = $this->cacheData ? 'true' : 'false'; + $data = !empty($this->submitData) && is_array( + $this->submitData + ) ? $this->submitData : 'js:{}'; + $data = CJavascript::encode($data); + + $js = <<cssClass}', function(){ + var span = $span; + var that = $(this); + var status = that.data('status'); + var rowid = that.data('rowid'); + var tr = $('#relatedinfo'+rowid); + var parent = that.parents('tr').eq(0); + var afterAjaxUpdate = {$afterAjaxUpdate}; + + if (status && status=='on'){return} + that.data('status','on'); + + if (tr.length && !tr.is(':visible') && {$cache}) + { + tr.slideDown(); + that.data('status','off'); + return; + }else if (tr.length && tr.is(':visible')) + { + tr.slideUp(); + that.data('status','off'); + return; + } + if (tr.length) + { + tr.find('td').html('{$loadingPic}'); + if (!tr.is(':visible')){ + tr.slideDown(); + } + } + else + { + var td = $('').html('{$loadingPic}').attr({'colspan':$span}); + tr = $('').prop({'id':'relatedinfo'+rowid}).append(td); + /* we need to maintain zebra styles :) */ + var fake = $('').append($('').attr({'colspan':$span})); + parent.after(tr); + tr.after(fake); + } + var data = $.extend({$data}, {id:rowid}); + $.ajax({ + url: '{$this->url}', + data: data, + success: function(data){ + tr.find('td').html(data); + that.data('status','off'); + if ($.isFunction(afterAjaxUpdate)) + { + afterAjaxUpdate(tr,rowid,data); + } + }, + error: function() + { + tr.find('td').html('{$this->ajaxErrorMessage}'); + that.data('status','off'); + } + }); +}); +EOD; + $cs->registerScript(__CLASS__ . '#' . $this->id, $js); + } +} diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/WhHighCharts.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/WhHighCharts.php new file mode 100644 index 0000000..7877016 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/WhHighCharts.php @@ -0,0 +1,112 @@ + + * $this->widget('yiiwheels.widgets.WhHighCharts', array( + * 'options'=>array( + * 'title' => array('text' => 'Fruit Consumption'), + * 'xAxis' => array( + * 'categories' => array('Apples', 'Bananas', 'Oranges') + * ), + * 'yAxis' => array( + * 'title' => array('text' => 'Fruit eaten') + * ), + * 'series' => array( + * array('name' => 'Jane', 'data' => array(1, 0, 4)), + * array('name' => 'John', 'data' => array(5, 7, 3)) + * ) + * ) + * )); + * + * + * To find out more about the possible {@link $options} attribute please refer to + * {@link http://www.hightcharts.com/ Highcharts site} + * + * @author Antonio Ramirez + * @copyright Copyright © 2amigos.us 2013- + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @package YiiWheels.widgets.highcharts + * @uses YiiWheels.WhHtml + */ +Yii::import('yiiwheels.helpers.WhHtml'); + +class WhHighCharts extends CWidget +{ + /** + * @var array $options the highcharts js configuration options + * @see http://api.highcharts.com/highcharts + */ + public $pluginOptions = array(); + + /** + * @var array $htmlOptions the HTML tag attributes + */ + public $htmlOptions = array(); + + /** + * Widget's initialization method + */ + public function init() + { + $this->attachBehavior('ywplugin', array('class' => 'yiiwheels.behaviors.WhPlugin')); + $this->htmlOptions['id'] = WhHtml::getOption('id', $this->htmlOptions, $this->getId()); + } + + /** + * Renders the widget. + */ + public function run() + { + // if there is no renderTo id, build the layer with current id and initialize renderTo option + if (!isset($this->options['chart']) || !isset($this->options['chart']['renderTo'])) { + echo WhHtml::tag('div', $this->htmlOptions); + + if (isset($this->pluginOptions['chart']) && is_array($this->pluginOptions['chart'])) { + $this->pluginOptions['chart']['renderTo'] = $this->htmlOptions['id']; + } else { + $this->pluginOptions['chart'] = array('renderTo' => $this->htmlOptions['id']); + } + + } + $this->registerClientScript(); + } + + /** + * Publishes and registers the necessary script files. + */ + protected function registerClientScript() + { + /* publish assets dir */ + $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'assets'; + $assetsUrl = $this->getAssetsUrl($path); + + /* @var $cs CClientScript */ + $cs = Yii::app()->getClientScript(); + + $cs->registerScriptFile($assetsUrl . '/js/highcharts.js'); + + /* register required files */ + $defaultOptions = array('exporting' => array('enabled' => true)); + + $this->pluginOptions = CMap::mergeArray($defaultOptions, $this->pluginOptions); + + if (isset($this->options['exporting']) && @$this->options['exporting']['enabled']) { + $cs->registerScriptFile($assetsUrl . '/js/modules/exporting.js'); + } + + if ($theme = WhHtml::getOption('theme', $this->pluginOptions)) { + $cs->registerScriptFile($assetsUrl . '/js/themes/' . $theme . '.js'); + } + + $options = CJavaScript::encode($this->pluginOptions); + + $cs->registerScript( + __CLASS__ . '#' . $this->getId(), + "var highchart{$this->getId()} = new Highcharts.Chart({$options});" + ); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/mootools-adapter.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/mootools-adapter.js new file mode 100644 index 0000000..39ed30e --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/mootools-adapter.js @@ -0,0 +1,92 @@ +/* + Highcharts JS v2.2.5 (2012-06-08) + MooTools adapter + + (c) 2010-2011 Torstein H?nsi + + License: www.highcharts.com/license + */ +(function () { + var e = window, i = document, f = e.MooTools.version.substring(0, 3), g = f === "1.2" || f === "1.1", j = g || f === "1.3", h = e.$extend || function () { + return Object.append.apply(Object, arguments) + }; + e.HighchartsAdapter = {init: function (a) { + var b = Fx.prototype, c = b.start, d = Fx.Morph.prototype, e = d.compute; + b.start = function (b, d) { + var e = this.element; + if (b.d)this.paths = a.init(e, e.d, this.toD); + c.apply(this, arguments); + return this + }; + d.compute = function (b, c, d) { + var f = this.paths; + if (f)this.element.attr("d", a.step(f[0], f[1], d, this.toD)); else return e.apply(this, + arguments) + } + }, adapterRun: function (a, b) { + return $(a).getStyle(b).toInt() + }, getScript: function (a, b) { + var c = i.getElementsByTagName("head")[0], d = i.createElement("script"); + d.type = "text/javascript"; + d.src = a; + d.onload = b; + c.appendChild(d) + }, animate: function (a, b, c) { + var d = a.attr, f = c && c.complete; + if (d && !a.setStyle)a.getStyle = a.attr, a.setStyle = function () { + var b = arguments; + a.attr.call(a, b[0], b[1][0]) + }, a.$family = function () { + return!0 + }; + e.HighchartsAdapter.stop(a); + c = new Fx.Morph(d ? a : $(a), h({transition: Fx.Transitions.Quad.easeInOut}, + c)); + if (d)c.element = a; + if (b.d)c.toD = b.d; + f && c.addEvent("complete", f); + c.start(b); + a.fx = c + }, each: function (a, b) { + return g ? $each(a, b) : Array.each(a, b) + }, map: function (a, b) { + return a.map(b) + }, grep: function (a, b) { + return a.filter(b) + }, merge: function () { + var a = arguments, b = [ + {} + ], c = a.length; + if (g)a = $merge.apply(null, a); else { + for (; c--;)typeof a[c] !== "boolean" && (b[c + 1] = a[c]); + a = Object.merge.apply(Object, b) + } + return a + }, offset: function (a) { + a = $(a).getOffsets(); + return{left: a.x, top: a.y} + }, extendWithEvents: function (a) { + a.addEvent || (a.nodeName ? + $(a) : h(a, new Events)) + }, addEvent: function (a, b, c) { + typeof b === "string" && (b === "unload" && (b = "beforeunload"), e.HighchartsAdapter.extendWithEvents(a), a.addEvent(b, c)) + }, removeEvent: function (a, b, c) { + typeof a !== "string" && (e.HighchartsAdapter.extendWithEvents(a), b ? (b === "unload" && (b = "beforeunload"), c ? a.removeEvent(b, c) : a.removeEvents && a.removeEvents(b)) : a.removeEvents()) + }, fireEvent: function (a, b, c, d) { + b = {type: b, target: a}; + b = j ? new Event(b) : new DOMEvent(b); + b = h(b, c); + b.preventDefault = function () { + d = null + }; + a.fireEvent && + a.fireEvent(b.type, b); + d && d(b) + }, washMouseEvent: function (a) { + a.pageX = a.page.x; + a.pageY = a.page.y; + return a + }, stop: function (a) { + a.fx && a.fx.cancel() + }} +})(); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/mootools-adapter.src.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/mootools-adapter.src.js new file mode 100644 index 0000000..dc1b798 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/mootools-adapter.src.js @@ -0,0 +1,326 @@ +/** + * @license Highcharts JS v2.2.5 (2012-06-08) + * MooTools adapter + * + * (c) 2010-2011 Torstein Hønsi + * + * License: www.highcharts.com/license + */ + +// JSLint options: +/*global Fx, $, $extend, $each, $merge, Events, Event, DOMEvent */ + +(function () { + + var win = window, + doc = document, + mooVersion = win.MooTools.version.substring(0, 3), // Get the first three characters of the version number + legacy = mooVersion === '1.2' || mooVersion === '1.1', // 1.1 && 1.2 considered legacy, 1.3 is not. + legacyEvent = legacy || mooVersion === '1.3', // In versions 1.1 - 1.3 the event class is named Event, in newer versions it is named DOMEvent. + $extend = win.$extend || function () { + return Object.append.apply(Object, arguments); + }; + + win.HighchartsAdapter = { + /** + * Initialize the adapter. This is run once as Highcharts is first run. + * @param {Object} pathAnim The helper object to do animations across adapters. + */ + init: function (pathAnim) { + var fxProto = Fx.prototype, + fxStart = fxProto.start, + morphProto = Fx.Morph.prototype, + morphCompute = morphProto.compute; + + // override Fx.start to allow animation of SVG element wrappers + /*jslint unparam: true*/ + /* allow unused parameters in fx functions */ + fxProto.start = function (from, to) { + var fx = this, + elem = fx.element; + + // special for animating paths + if (from.d) { + //this.fromD = this.element.d.split(' '); + fx.paths = pathAnim.init( + elem, + elem.d, + fx.toD + ); + } + fxStart.apply(fx, arguments); + + return this; // chainable + }; + + // override Fx.step to allow animation of SVG element wrappers + morphProto.compute = function (from, to, delta) { + var fx = this, + paths = fx.paths; + + if (paths) { + fx.element.attr( + 'd', + pathAnim.step(paths[0], paths[1], delta, fx.toD) + ); + } else { + return morphCompute.apply(fx, arguments); + } + }; + /*jslint unparam: false*/ + }, + + /** + * Run a general method on the framework, following jQuery syntax + * @param {Object} el The HTML element + * @param {String} method Which method to run on the wrapped element + */ + adapterRun: function (el, method) { + + // This currently works for getting inner width and height. If adding + // more methods later, we need a conditional implementation for each. + return $(el).getStyle(method).toInt(); + + }, + + /** + * Downloads a script and executes a callback when done. + * @param {String} scriptLocation + * @param {Function} callback + */ + getScript: function (scriptLocation, callback) { + // We cannot assume that Assets class from mootools-more is available so instead insert a script tag to download script. + var head = doc.getElementsByTagName('head')[0]; + var script = doc.createElement('script'); + + script.type = 'text/javascript'; + script.src = scriptLocation; + script.onload = callback; + + head.appendChild(script); + }, + + /** + * Animate a HTML element or SVG element wrapper + * @param {Object} el + * @param {Object} params + * @param {Object} options jQuery-like animation options: duration, easing, callback + */ + animate: function (el, params, options) { + var isSVGElement = el.attr, + effect, + complete = options && options.complete; + + if (isSVGElement && !el.setStyle) { + // add setStyle and getStyle methods for internal use in Moo + el.getStyle = el.attr; + el.setStyle = function () { // property value is given as array in Moo - break it down + var args = arguments; + el.attr.call(el, args[0], args[1][0]); + }; + // dirty hack to trick Moo into handling el as an element wrapper + el.$family = function () { + return true; + }; + } + + // stop running animations + win.HighchartsAdapter.stop(el); + + // define and run the effect + effect = new Fx.Morph( + isSVGElement ? el : $(el), + $extend({ + transition: Fx.Transitions.Quad.easeInOut + }, options) + ); + + // Make sure that the element reference is set when animating svg elements + if (isSVGElement) { + effect.element = el; + } + + // special treatment for paths + if (params.d) { + effect.toD = params.d; + } + + // jQuery-like events + if (complete) { + effect.addEvent('complete', complete); + } + + // run + effect.start(params); + + // record for use in stop method + el.fx = effect; + }, + + /** + * MooTool's each function + * + */ + each: function (arr, fn) { + return legacy ? + $each(arr, fn) : + Array.each(arr, fn); + }, + + /** + * Map an array + * @param {Array} arr + * @param {Function} fn + */ + map: function (arr, fn) { + return arr.map(fn); + }, + + /** + * Grep or filter an array + * @param {Array} arr + * @param {Function} fn + */ + grep: function (arr, fn) { + return arr.filter(fn); + }, + + /** + * Deep merge two objects and return a third + */ + merge: function () { + var args = arguments, + args13 = [ + {} + ], // MooTools 1.3+ + i = args.length, + ret; + + if (legacy) { + ret = $merge.apply(null, args); + } else { + while (i--) { + // Boolean argumens should not be merged. + // JQuery explicitly skips this, so we do it here as well. + if (typeof args[i] !== 'boolean') { + args13[i + 1] = args[i]; + } + } + ret = Object.merge.apply(Object, args13); + } + + return ret; + }, + + /** + * Get the offset of an element relative to the top left corner of the web page + */ + offset: function (el) { + var offsets = $(el).getOffsets(); + return { + left: offsets.x, + top: offsets.y + }; + }, + + /** + * Extends an object with Events, if its not done + */ + extendWithEvents: function (el) { + // if the addEvent method is not defined, el is a custom Highcharts object + // like series or point + if (!el.addEvent) { + if (el.nodeName) { + el = $(el); // a dynamically generated node + } else { + $extend(el, new Events()); // a custom object + } + } + }, + + /** + * Add an event listener + * @param {Object} el HTML element or custom object + * @param {String} type Event type + * @param {Function} fn Event handler + */ + addEvent: function (el, type, fn) { + if (typeof type === 'string') { // chart broke due to el being string, type function + + if (type === 'unload') { // Moo self destructs before custom unload events + type = 'beforeunload'; + } + + win.HighchartsAdapter.extendWithEvents(el); + + el.addEvent(type, fn); + } + }, + + removeEvent: function (el, type, fn) { + if (typeof el === 'string') { + // el.removeEvents below apperantly calls this method again. Do not quite understand why, so for now just bail out. + return; + } + + win.HighchartsAdapter.extendWithEvents(el); + if (type) { + if (type === 'unload') { // Moo self destructs before custom unload events + type = 'beforeunload'; + } + + if (fn) { + el.removeEvent(type, fn); + } else if (el.removeEvents) { // #958 + el.removeEvents(type); + } + } else { + el.removeEvents(); + } + }, + + fireEvent: function (el, event, eventArguments, defaultFunction) { + var eventArgs = { + type: event, + target: el + }; + // create an event object that keeps all functions + event = legacyEvent ? new Event(eventArgs) : new DOMEvent(eventArgs); + event = $extend(event, eventArguments); + // override the preventDefault function to be able to use + // this for custom events + event.preventDefault = function () { + defaultFunction = null; + }; + // if fireEvent is not available on the object, there hasn't been added + // any events to it above + if (el.fireEvent) { + el.fireEvent(event.type, event); + } + + // fire the default if it is passed and it is not prevented above + if (defaultFunction) { + defaultFunction(event); + } + }, + + /** + * Set back e.pageX and e.pageY that MooTools has abstracted away + */ + washMouseEvent: function (e) { + e.pageX = e.page.x; + e.pageY = e.page.y; + return e; + }, + + /** + * Stop running animations on the object + */ + stop: function (el) { + if (el.fx) { + el.fx.cancel(); + } + } + }; + +}()); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/prototype-adapter.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/prototype-adapter.js new file mode 100644 index 0000000..c54a756 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/prototype-adapter.js @@ -0,0 +1,101 @@ +/* + Highcharts JS v2.2.5 (2012-06-08) + Prototype adapter + + @author Michael Nelson, Torstein H?nsi. + + Feel free to use and modify this script. + Highcharts license: www.highcharts.com/license. + */ +var HighchartsAdapter = function () { + var g = typeof Effect !== "undefined"; + return{init: function (c) { + if (g)Effect.HighchartsTransition = Class.create(Effect.Base, {initialize: function (a, b, d, e) { + var f; + this.element = a; + this.key = b; + f = a.attr ? a.attr(b) : $(a).getStyle(b); + if (b === "d")this.paths = c.init(a, a.d, d), this.toD = d, f = 0, d = 1; + this.start(Object.extend(e || {}, {from: f, to: d, attribute: b})) + }, setup: function () { + HighchartsAdapter._extend(this.element); + if (!this.element._highchart_animation)this.element._highchart_animation = {}; + this.element._highchart_animation[this.key] = + this + }, update: function (a) { + var b = this.paths, d = this.element; + b && (a = c.step(b[0], b[1], a, this.toD)); + d.attr ? d.attr(this.options.attribute, a) : (b = {}, b[this.options.attribute] = a, $(d).setStyle(b)) + }, finish: function () { + delete this.element._highchart_animation[this.key] + }}) + }, adapterRun: function (c, a) { + return parseInt($(c).getStyle(a), 10) + }, getScript: function (c, a) { + var b = $$("head")[0]; + b && b.appendChild((new Element("script", {type: "text/javascript", src: c})).observe("load", a)) + }, addNS: function (c) { + var a = /^(?:click|mouse(?:down|up|over|move|out))$/; + return/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/.test(c) || a.test(c) ? c : "h:" + c + }, addEvent: function (c, a, b) { + c.addEventListener || c.attachEvent ? Event.observe($(c), HighchartsAdapter.addNS(a), b) : (HighchartsAdapter._extend(c), c._highcharts_observe(a, b)) + }, animate: function (c, a, b) { + var d, b = b || {}; + b.delay = 0; + b.duration = (b.duration || 500) / 1E3; + b.afterFinish = b.complete; + if (g)for (d in a)new Effect.HighchartsTransition($(c), d, a[d], b); else { + if (c.attr)for (d in a)c.attr(d, a[d]); + b.complete && + b.complete() + } + c.attr || $(c).setStyle(a) + }, stop: function (c) { + var a; + if (c._highcharts_extended && c._highchart_animation)for (a in c._highchart_animation)c._highchart_animation[a].cancel() + }, each: function (c, a) { + $A(c).each(a) + }, offset: function (c) { + return $(c).cumulativeOffset() + }, fireEvent: function (c, a, b, d) { + c.fire ? c.fire(HighchartsAdapter.addNS(a), b) : c._highcharts_extended && (b = b || {}, c._highcharts_fire(a, b)); + b && b.defaultPrevented && (d = null); + d && d(b) + }, removeEvent: function (c, a, b) { + $(c).stopObserving && (a && (a = HighchartsAdapter.addNS(a)), + $(c).stopObserving(a, b)); + window === c ? Event.stopObserving(c, a, b) : (HighchartsAdapter._extend(c), c._highcharts_stop_observing(a, b)) + }, washMouseEvent: function (c) { + return c + }, grep: function (c, a) { + return c.findAll(a) + }, map: function (c, a) { + return c.map(a) + }, merge: function () { + function c(a, b) { + var d, e; + for (e in b)d = b[e], a[e] = d && typeof d === "object" && d.constructor !== Array && typeof d.nodeType !== "number" ? c(a[e] || {}, d) : b[e]; + return a + } + + return function () { + var a = arguments, b, d = {}; + for (b = 0; b < a.length; b++)d = c(d, a[b]); + return d + }.apply(this, + arguments) + }, _extend: function (c) { + c._highcharts_extended || Object.extend(c, {_highchart_events: {}, _highchart_animation: null, _highcharts_extended: !0, _highcharts_observe: function (a, b) { + this._highchart_events[a] = [this._highchart_events[a], b].compact().flatten() + }, _highcharts_stop_observing: function (a, b) { + a ? b ? this._highchart_events[a] = [this._highchart_events[a]].compact().flatten().without(b) : delete this._highchart_events[a] : this._highchart_events = {} + }, _highcharts_fire: function (a, b) { + (this._highchart_events[a] || + []).each(function (a) { + if (!b.stopped)b.preventDefault = function () { + b.defaultPrevented = !0 + }, a.bind(this)(b) === !1 && b.preventDefault() + }.bind(this)) + }}) + }} +}(); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/prototype-adapter.src.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/prototype-adapter.src.js new file mode 100644 index 0000000..2a779e1 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/adapters/prototype-adapter.src.js @@ -0,0 +1,382 @@ +/** + * @license Highcharts JS v2.2.5 (2012-06-08) + * Prototype adapter + * + * @author Michael Nelson, Torstein Hønsi. + * + * Feel free to use and modify this script. + * Highcharts license: www.highcharts.com/license. + */ + +// JSLint options: +/*global Effect, Class, Event, Element, $, $$, $A */ + +// Adapter interface between prototype and the Highcharts charting library +var HighchartsAdapter = (function () { + + var hasEffect = typeof Effect !== 'undefined'; + + return { + + /** + * Initialize the adapter. This is run once as Highcharts is first run. + * @param {Object} pathAnim The helper object to do animations across adapters. + */ + init: function (pathAnim) { + if (hasEffect) { + /** + * Animation for Highcharts SVG element wrappers only + * @param {Object} element + * @param {Object} attribute + * @param {Object} to + * @param {Object} options + */ + Effect.HighchartsTransition = Class.create(Effect.Base, { + initialize: function (element, attr, to, options) { + var from, + opts; + + this.element = element; + this.key = attr; + from = element.attr ? element.attr(attr) : $(element).getStyle(attr); + + // special treatment for paths + if (attr === 'd') { + this.paths = pathAnim.init( + element, + element.d, + to + ); + this.toD = to; + + + // fake values in order to read relative position as a float in update + from = 0; + to = 1; + } + + opts = Object.extend((options || {}), { + from: from, + to: to, + attribute: attr + }); + this.start(opts); + }, + setup: function () { + HighchartsAdapter._extend(this.element); + // If this is the first animation on this object, create the _highcharts_animation helper that + // contain pointers to the animation objects. + if (!this.element._highchart_animation) { + this.element._highchart_animation = {}; + } + + // Store a reference to this animation instance. + this.element._highchart_animation[this.key] = this; + }, + update: function (position) { + var paths = this.paths, + element = this.element, + obj; + + if (paths) { + position = pathAnim.step(paths[0], paths[1], position, this.toD); + } + + if (element.attr) { // SVGElement + element.attr(this.options.attribute, position); + + } else { // HTML, #409 + obj = {}; + obj[this.options.attribute] = position; + $(element).setStyle(obj); + } + + }, + finish: function () { + // Delete the property that holds this animation now that it is finished. + // Both canceled animations and complete ones gets a 'finish' call. + delete this.element._highchart_animation[this.key]; + } + }); + } + }, + + /** + * Run a general method on the framework, following jQuery syntax + * @param {Object} el The HTML element + * @param {String} method Which method to run on the wrapped element + */ + adapterRun: function (el, method) { + + // This currently works for getting inner width and height. If adding + // more methods later, we need a conditional implementation for each. + return parseInt($(el).getStyle(method), 10); + + }, + + /** + * Downloads a script and executes a callback when done. + * @param {String} scriptLocation + * @param {Function} callback + */ + getScript: function (scriptLocation, callback) { + var head = $$('head')[0]; // Returns an array, so pick the first element. + if (head) { + // Append a new 'script' element, set its type and src attributes, add a 'load' handler that calls the callback + head.appendChild(new Element('script', { type: 'text/javascript', src: scriptLocation}).observe('load', callback)); + } + }, + + /** + * Custom events in prototype needs to be namespaced. This method adds a namespace 'h:' in front of + * events that are not recognized as native. + */ + addNS: function (eventName) { + var HTMLEvents = /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/, + MouseEvents = /^(?:click|mouse(?:down|up|over|move|out))$/; + return (HTMLEvents.test(eventName) || MouseEvents.test(eventName)) ? + eventName : + 'h:' + eventName; + }, + + // el needs an event to be attached. el is not necessarily a dom element + addEvent: function (el, event, fn) { + if (el.addEventListener || el.attachEvent) { + Event.observe($(el), HighchartsAdapter.addNS(event), fn); + + } else { + HighchartsAdapter._extend(el); + el._highcharts_observe(event, fn); + } + }, + + // motion makes things pretty. use it if effects is loaded, if not... still get to the end result. + animate: function (el, params, options) { + var key, + fx; + + // default options + options = options || {}; + options.delay = 0; + options.duration = (options.duration || 500) / 1000; + options.afterFinish = options.complete; + + // animate wrappers and DOM elements + if (hasEffect) { + for (key in params) { + // The fx variable is seemingly thrown away here, but the Effect.setup will add itself to the _highcharts_animation object + // on the element itself so its not really lost. + fx = new Effect.HighchartsTransition($(el), key, params[key], options); + } + } else { + if (el.attr) { // #409 without effects + for (key in params) { + el.attr(key, params[key]); + } + } + if (options.complete) { + options.complete(); + } + } + + if (!el.attr) { // HTML element, #409 + $(el).setStyle(params); + } + }, + + // this only occurs in higcharts 2.0+ + stop: function (el) { + var key; + if (el._highcharts_extended && el._highchart_animation) { + for (key in el._highchart_animation) { + // Cancel the animation + // The 'finish' function in the Effect object will remove the reference + el._highchart_animation[key].cancel(); + } + } + }, + + // um.. each + each: function (arr, fn) { + $A(arr).each(fn); + }, + + /** + * Get the cumulative offset relative to the top left of the page. This method, unlike its + * jQuery and MooTools counterpart, still suffers from issue #208 regarding the position + * of a chart within a fixed container. + */ + offset: function (el) { + return $(el).cumulativeOffset(); + }, + + // fire an event based on an event name (event) and an object (el). + // again, el may not be a dom element + fireEvent: function (el, event, eventArguments, defaultFunction) { + if (el.fire) { + el.fire(HighchartsAdapter.addNS(event), eventArguments); + } else if (el._highcharts_extended) { + eventArguments = eventArguments || {}; + el._highcharts_fire(event, eventArguments); + } + + if (eventArguments && eventArguments.defaultPrevented) { + defaultFunction = null; + } + + if (defaultFunction) { + defaultFunction(eventArguments); + } + }, + + removeEvent: function (el, event, handler) { + if ($(el).stopObserving) { + if (event) { + event = HighchartsAdapter.addNS(event); + } + $(el).stopObserving(event, handler); + } + if (window === el) { + Event.stopObserving(el, event, handler); + } else { + HighchartsAdapter._extend(el); + el._highcharts_stop_observing(event, handler); + } + }, + + washMouseEvent: function (e) { + return e; + }, + + // um, grep + grep: function (arr, fn) { + return arr.findAll(fn); + }, + + // um, map + map: function (arr, fn) { + return arr.map(fn); + }, + + // deep merge. merge({a : 'a', b : {b1 : 'b1', b2 : 'b2'}}, {b : {b2 : 'b2_prime'}, c : 'c'}) => {a : 'a', b : {b1 : 'b1', b2 : 'b2_prime'}, c : 'c'} + /*merge: function(){ + function doCopy(copy, original) { + var value, + key, + undef, + nil, + same, + obj, + arr, + node; + + for (key in original) { + value = original[key]; + undef = typeof(value) === 'undefined'; + nil = value === null; + same = original === copy[key]; + + if (undef || nil || same) { + continue; + } + + obj = typeof(value) === 'object'; + arr = value && obj && value.constructor == Array; + node = !!value.nodeType; + + if (obj && !arr && !node) { + copy[key] = doCopy(typeof copy[key] == 'object' ? copy[key] : {}, value); + } + else { + copy[key] = original[key]; + } + } + return copy; + } + + var args = arguments, retVal = {}; + + for (var i = 0; i < args.length; i++) { + retVal = doCopy(retVal, args[i]); + } + + return retVal; + },*/ + merge: function () { // the built-in prototype merge function doesn't do deep copy + function doCopy(copy, original) { + var value, key; + + for (key in original) { + value = original[key]; + if (value && typeof value === 'object' && value.constructor !== Array && + typeof value.nodeType !== 'number') { + copy[key] = doCopy(copy[key] || {}, value); // copy + + } else { + copy[key] = original[key]; + } + } + return copy; + } + + function merge() { + var args = arguments, + i, + retVal = {}; + + for (i = 0; i < args.length; i++) { + retVal = doCopy(retVal, args[i]); + + } + return retVal; + } + + return merge.apply(this, arguments); + }, + + // extend an object to handle highchart events (highchart objects, not svg elements). + // this is a very simple way of handling events but whatever, it works (i think) + _extend: function (object) { + if (!object._highcharts_extended) { + Object.extend(object, { + _highchart_events: {}, + _highchart_animation: null, + _highcharts_extended: true, + _highcharts_observe: function (name, fn) { + this._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten(); + }, + _highcharts_stop_observing: function (name, fn) { + if (name) { + if (fn) { + this._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn); + } else { + delete this._highchart_events[name]; + } + } else { + this._highchart_events = {}; + } + }, + _highcharts_fire: function (name, args) { + (this._highchart_events[name] || []).each(function (fn) { + // args is never null here + if (args.stopped) { + return; // "throw $break" wasn't working. i think because of the scope of 'this'. + } + + // Attach a simple preventDefault function to skip default handler if called + args.preventDefault = function () { + args.defaultPrevented = true; + }; + + // If the event handler return false, prevent the default handler from executing + if (fn.bind(this)(args) === false) { + args.preventDefault(); + } + } + .bind(this)); + } + }); + } + } + }; +}()); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts-more.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts-more.js new file mode 100644 index 0000000..8236db8 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts-more.js @@ -0,0 +1,198 @@ +/* + Highcharts JS v2.2.5 (2012-06-08) + + (c) 2009-2011 Torstein H?nsi + + License: www.highcharts.com/license + */ +(function (g, v) { + var o = g.each, s = g.extend, p = g.merge, w = g.map, j = g.pick, q = g.pInt, i = g.getOptions().plotOptions, k = g.seriesTypes, t = g.Series, m = function () { + }, r = g.Axis.prototype, l = g.Tick.prototype, x = {redraw: function () { + this.isDirty = !1 + }, render: function () { + this.isDirty = !1 + }, setScale: m, setCategories: m, setTitle: m}, u = {isRadial: !0, defaultRadialGaugeOptions: {center: ["50%", "50%"], labels: {align: "center", x: 0, y: null}, minorGridLineWidth: 0, minorTickInterval: "auto", minorTickLength: 10, minorTickPosition: "inside", minorTickWidth: 1, + plotBands: [], size: ["90%"], tickLength: 10, tickPosition: "inside", tickWidth: 2, title: {rotation: 0}, zIndex: 2}, defaultRadialXOptions: {center: ["50%", "50%"], labels: {align: "center", distance: 15, x: 0, y: null}, maxPadding: 0, minPadding: 0, size: ["90%"]}, defaultRadialYOptions: {center: ["50%", "50%"], labels: {align: "left", x: 3, y: -2}, size: ["90%"], title: {x: -4, text: null}}, defaultBackgroundOptions: {shape: "circle", borderWidth: 1, borderColor: "silver", backgroundColor: {linearGradient: {x1: 0, y1: 0, x2: 0, y2: 1}, stops: [ + [0, "#FFF"], + [1, "#DDD"] + ]}, + from: Number.MIN_VALUE, innerRadius: 0, to: Number.MAX_VALUE, outerRadius: "105%"}, setOptions: function (a) { + var b = this, c; + b.options = c = p(b.defaultOptions, b.isXAxis ? {} : b.defaultYAxisOptions, b.defaultRadialOptions, a); + o([].concat(g.splat(a.background || {})).reverse(), function (a) { + a = p(b.defaultBackgroundOptions, a); + a.color = a.backgroundColor; + c.plotBands.unshift(a) + }) + }, getOffset: function () { + r.getOffset.call(this); + this.chart.axisOffset[this.side] = 0; + this.center = k.pie.prototype.getCenter.call(this) + }, getLinePath: function (a) { + var b = + this.center, a = j(a, b[2] / 2 - this.offset); + return this.chart.renderer.symbols.arc(this.left + b[0], this.top + b[1], a, a, {start: this.startAngleRad, end: this.endAngleRad, open: !0, innerR: 0}) + }, setAxisTranslation: function () { + r.setAxisTranslation.call(this); + if (this.center)this.transA = this.isCircular ? (this.endAngleRad - this.startAngleRad) / (this.max - this.min + (this.closestPointRange || 0) || 1) : this.center[2] / 2 / (this.max - this.min || 1), this.minPixelPadding = this.transA * ((this.pointRange || 0) / 2) + }, setAxisSize: function () { + r.setAxisSize.call(this); + if (this.center)this.len = this.width = this.height = this.isCircular ? this.center[2] * (this.endAngleRad - this.startAngleRad) / 2 : this.center[2] / 2 + }, getPosition: function (a, b) { + if (!this.isCircular)b = this.translate(a), a = this.min; + return this.postTranslate(this.translate(a), j(b, this.center[2] / 2) - this.offset) + }, postTranslate: function (a, b) { + var c = this.chart, d = this.center, a = this.startAngleRad + a; + return{x: c.plotLeft + d[0] + Math.cos(a) * b, y: c.plotTop + d[1] + Math.sin(a) * b} + }, getPlotBandPath: function (a, b, c) { + var d = this.center, e = this.startAngleRad, + h = d[2] / 2, f = [j(c.outerRadius, "100%"), c.innerRadius, j(c.thickness, 10)], g = /%$/, n, f = w(f, function (a) { + g.test(a) && (a = q(a, 10) * h / 100); + return a + }); + c.shape === "circle" ? (a = -Math.PI / 2, b = Math.PI * 1.5, n = !0) : (a = e + this.translate(a), b = e + this.translate(b)); + return this.chart.renderer.symbols.arc(this.left + d[0], this.top + d[1], f[0], f[0], {start: a, end: b, innerR: j(f[1], f[0] - f[2]), open: n}) + }, getPlotLinePath: function (a) { + var b = this.center, c = this.chart, d = this.getPosition(a); + return this.isCircular ? ["M", b[0] + c.plotLeft, b[1] + c.plotTop, + "L", d.x, d.y] : u.getLinePath.call(this, this.translate(a)) + }, getTitlePosition: function () { + var a = this.center, b = this.chart, c = this.options.title; + return{x: b.plotLeft + a[0] + (c.x || 0), y: b.plotTop + a[1] - {high: 0.5, middle: 0.25, low: 0}[this.options.title.align] * a[2] + (c.y || 0)} + }}; + r.init = function (a) { + return function (b, c) { + var d = b.angular, e = b.polar, h = c.isX, f; + if (d) { + if (s(this, h ? x : u), f = !h)this.defaultRadialOptions = this.defaultGaugeOptions + } else if (e)s(this, u), this.defaultRadialOptions = (f = h) ? this.defaultRadialXOptions : this.defaultRadialYOptions; + a.apply(this, arguments); + if (d || e)d = this.options, this.startAngleRad = (d.startAngle - 90) * Math.PI / 180, this.endAngleRad = (d.endAngle - 90) * Math.PI / 180, this.offset = d.offset || 0, this.isCircular = f + } + }(r.init); + l.getPosition = function (a) { + return function () { + var b = this.axis, c = arguments; + return b.getPosition ? b.getPosition(c[1]) : a.apply(this, c) + } + }(l.getPosition); + l.getLabelPosition = function (a) { + return function () { + var b = this.axis, c = b.options.labels, d = this.label, e = c.y, h; + b.isRadial ? (h = b.getPosition(this.pos, b.center[2] / 2 + j(c.distance, + -25)), c.rotation === "auto" ? d.attr({rotation: (b.translate(this.pos) + b.startAngleRad + Math.PI / 2) / Math.PI * 180}) : e === null && (e = q(d.styles.lineHeight) * 0.9 - d.getBBox().height / 2), h.x += c.x, h.y += e) : h = a.apply(this, arguments); + return h + } + }(l.getLabelPosition); + l.getMarkPath = function (a) { + return function (b, c, d) { + var e = this.axis; + e.isRadial ? (e = e.getPosition(this.pos, e.center[2] / 2 + d), e = ["M", b, c, "L", e.x, e.y]) : e = a.apply(this, arguments); + return e + } + }(l.getMarkPath); + i.arearange = p(i.area, {lineWidth: 0, threshold: null, tooltip: {pointFormat: '{series.name}: {point.low} - {point.high}'}, + trackByArea: !0, dataLabels: {yHigh: -6, yLow: 16}}); + l = g.extendClass(g.Point, {applyOptions: function (a) { + var b = this.series, c = 0; + if (typeof a === "object" && typeof a.length !== "number")s(this, a), this.options = a; else if (a.length) { + if (a.length === 3) { + if (typeof a[0] === "string")this.name = a[0]; else if (typeof a[0] === "number")this.x = a[0]; + c++ + } + this.low = a[c++]; + this.high = a[c++] + } + if (this.high === null)this.low = null; + this.y = this.low; + if (this.x === v && b)this.x = b.autoIncrement(); + return this + }, toYData: function () { + return[this.low, this.high] + }}); + k.arearange = g.extendClass(k.area, {type: "arearange", valueCount: 2, pointClass: l, translate: function () { + var a = this.yAxis; + k.area.prototype.translate.apply(this); + o(this.points, function (b) { + if (b.y !== null)b.plotLow = b.plotY, b.plotHigh = a.translate(b.high, 0, 1, 0, 1) + }) + }, getSegmentPath: function (a) { + for (var b = [], c = a.length, d = t.prototype.getSegmentPath, e; c--;)e = a[c], b.push({plotX: e.plotX, plotY: e.plotHigh}); + a = d.call(this, a); + d = d.call(this, b); + b = [].concat(a, d); + d[0] = "L"; + this.areaPath = this.areaPath.concat(a, d); + return b + }, drawDataLabels: function () { + var a = + this.points, b = a.length, c, d = [], e = t.prototype.drawDataLabels, h = this.options.dataLabels, f; + for (c = b; c--;)f = a[c], f.y = f.high, f.plotY = f.plotHigh, d[c] = f.dataLabel, f.dataLabel = f.dataLabelUpper, h.y = h.yHigh; + e.apply(this, arguments); + for (c = b; c--;)f = a[c], f.dataLabelUpper = f.dataLabel, f.dataLabel = d[c], f.y = f.low, f.plotY = f.plotLow, h.y = h.yLow; + e.apply(this, arguments) + }, drawPoints: m}); + i.gauge = p(i.line, {dataLabels: {enabled: !0, y: 30, borderWidth: 1, borderColor: "silver", borderRadius: 3, style: {fontWeight: "bold"}}, dial: {}, pivot: {}, + tooltip: {headerFormat: ""}, showInLegend: !1}); + i = {type: "gauge", pointClass: g.extendClass(g.Point, {setState: function (a) { + this.state = a + }}), angular: !0, translate: function () { + var a = this, b = a.yAxis, c = b.center; + a.generatePoints(); + o(a.points, function (d) { + var e = p(a.options.dial, d.dial), h = q(j(e.radius, 80)) * c[2] / 200, f = q(j(e.baseLength, 70)) * h / 100, g = q(j(e.rearLength, 10)) * h / 100, n = e.baseWidth || 3, i = e.topWidth || 1; + d.shapeType = "path"; + d.shapeArgs = {d: e.path || ["M", -g, -n / 2, "L", f, -n / 2, h, -i / 2, h, i / 2, f, n / 2, -g, n / 2], translateX: c[0], translateY: c[1], + rotation: (b.startAngleRad + b.translate(d.y)) * 180 / Math.PI}; + d.plotX = c[0]; + d.plotY = c[1] + }) + }, drawPoints: function () { + var a = this, b = a.yAxis.center, c = a.pivot, d = a.options, e = d.pivot, h = d.dial; + o(a.points, function (b) { + var c = b.graphic, d = b.shapeArgs, e = d.d; + c ? (c.animate(d), d.d = e) : b.graphic = a.chart.renderer[b.shapeType](d).attr({stroke: h.borderColor || "none", "stroke-width": h.borderWidth || 0, fill: h.backgroundColor || "black"}).add(a.group) + }); + c ? c.animate({cx: b[0], cy: b[1]}) : a.pivot = a.chart.renderer.circle(b[0], b[1], j(e.radius, + 5)).attr({"stroke-width": e.borderWidth || 0, stroke: e.borderColor || "silver", fill: e.backgroundColor || "black"}).add(a.group) + }, animate: function () { + var a = this; + o(a.points, function (b) { + var c = b.graphic; + c && (c.attr({rotation: a.yAxis.startAngleRad * 180 / Math.PI}), c.animate({rotation: b.shapeArgs.rotation}, a.options.animation)) + }); + a.animate = null + }, render: function () { + this.createGroup(); + k.pie.prototype.render.call(this) + }, setData: k.pie.prototype.setData, drawTracker: k.column.prototype.drawTracker}; + k.gauge = g.extendClass(k.line, + i); + i = t.prototype; + m = k.column.prototype; + i.toXY = function (a) { + var b, c = this.chart; + a.rectPlotX = a.plotX; + a.rectPlotY = a.plotY; + b = this.xAxis.postTranslate(a.plotX, this.yAxis.len - a.plotY); + a.plotX = a.polarPlotX = b.x - c.plotLeft; + a.plotY = a.polarPlotY = b.y - c.plotTop + }; + i.translate = function (a) { + return function () { + a.apply(this, arguments); + if (this.xAxis.getPosition && this.type !== "column")for (var b = this.points, c = b.length; c--;)this.toXY(b[c]) + } + }(i.translate); + m.translate = function (a) { + return function () { + var b = this.xAxis, c = this.yAxis.len, + d = b.center, e = b.startAngleRad, h = this.chart.renderer, f, g; + a.apply(this, arguments); + if (b.isRadial) { + b = this.points; + for (g = b.length; g--;)f = b[g], f.shapeType = "path", f.shapeArgs = {d: h.symbols.arc(d[0], d[1], c - f.plotY, null, {start: e + f.barX, end: e + f.barX + f.pointWidth, innerR: c - f.yBottom})}, this.toXY(f) + } + } + }(m.translate) +})(Highcharts); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts.js new file mode 100644 index 0000000..433eee5 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts.js @@ -0,0 +1,3273 @@ +/* + Highcharts JS v2.2.5 (2012-06-08) + + (c) 2009-2011 Torstein H?nsi + + License: www.highcharts.com/license + */ +(function () { + function u(a, b) { + var c; + a || (a = {}); + for (c in b)a[c] = b[c]; + return a + } + + function la() { + for (var a = 0, b = arguments, c = b.length, d = {}; a < c; a++)d[b[a++]] = b[a]; + return d + } + + function w(a, b) { + return parseInt(a, b || 10) + } + + function ra(a) { + return typeof a === "string" + } + + function aa(a) { + return typeof a === "object" + } + + function Ja(a) { + return Object.prototype.toString.call(a) === "[object Array]" + } + + function Ka(a) { + return typeof a === "number" + } + + function ma(a) { + return L.log(a) / L.LN10 + } + + function ba(a) { + return L.pow(10, a) + } + + function za(a, b) { + for (var c = + a.length; c--;)if (a[c] === b) { + a.splice(c, 1); + break + } + } + + function s(a) { + return a !== A && a !== null + } + + function z(a, b, c) { + var d, e; + if (ra(b))s(c) ? a.setAttribute(b, c) : a && a.getAttribute && (e = a.getAttribute(b)); else if (s(b) && aa(b))for (d in b)a.setAttribute(d, b[d]); + return e + } + + function na(a) { + return Ja(a) ? a : [a] + } + + function o() { + var a = arguments, b, c, d = a.length; + for (b = 0; b < d; b++)if (c = a[b], typeof c !== "undefined" && c !== null)return c + } + + function F(a, b) { + if (La && b && b.opacity !== A)b.filter = "alpha(opacity=" + b.opacity * 100 + ")"; + u(a.style, b) + } + + function S(a, b, c, d, e) { + a = B.createElement(a); + b && u(a, b); + e && F(a, {padding: 0, border: U, margin: 0}); + c && F(a, c); + d && d.appendChild(a); + return a + } + + function ca(a, b) { + var c = function () { + }; + c.prototype = new a; + u(c.prototype, b); + return c + } + + function Xa(a, b, c, d) { + var e = V.lang, f = a; + b === -1 ? (b = (a || 0).toString(), a = b.indexOf(".") > -1 ? b.split(".")[1].length : 0) : a = isNaN(b = M(b)) ? 2 : b; + var b = a, c = c === void 0 ? e.decimalPoint : c, d = d === void 0 ? e.thousandsSep : d, e = f < 0 ? "-" : "", a = String(w(f = M(+f || 0).toFixed(b))), g = a.length > 3 ? a.length % 3 : 0; + return e + (g ? a.substr(0, g) + d : "") + + a.substr(g).replace(/(\d{3})(?=\d)/g, "$1" + d) + (b ? c + M(f - a).toFixed(b).slice(2) : "") + } + + function sa(a, b) { + return Array((b || 2) + 1 - String(a).length).join(0) + a + } + + function gb(a, b, c, d) { + var e, c = o(c, 1); + e = a / c; + b || (b = [1, 2, 2.5, 5, 10], d && d.allowDecimals === !1 && (c === 1 ? b = [1, 2, 5, 10] : c <= 0.1 && (b = [1 / c]))); + for (d = 0; d < b.length; d++)if (a = b[d], e <= (b[d] + (b[d + 1] || b[d])) / 2)break; + a *= c; + return a + } + + function Ob(a, b) { + var c = b || [ + [vb, [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], + [hb, [1, 2, 5, 10, 15, 30]], + [Ya, [1, 2, 5, 10, 15, 30]], + [Ma, [1, 2, 3, 4, 6, 8, 12]], + [oa, [1, 2]], + [Za, + [1, 2]], + [Na, [1, 2, 3, 4, 6]], + [ta, null] + ], d = c[c.length - 1], e = D[d[0]], f = d[1], g; + for (g = 0; g < c.length; g++)if (d = c[g], e = D[d[0]], f = d[1], c[g + 1] && a <= (e * f[f.length - 1] + D[c[g + 1][0]]) / 2)break; + e === D[ta] && a < 5 * e && (f = [1, 2, 5]); + e === D[ta] && a < 5 * e && (f = [1, 2, 5]); + c = gb(a / e, f); + return{unitRange: e, count: c, unitName: d[0]} + } + + function Pb(a, b, c, d) { + var e = [], f = {}, g = V.global.useUTC, h, i = new Date(b), b = a.unitRange, j = a.count; + b >= D[hb] && (i.setMilliseconds(0), i.setSeconds(b >= D[Ya] ? 0 : j * W(i.getSeconds() / j))); + if (b >= D[Ya])i[wb](b >= D[Ma] ? 0 : j * W(i[ib]() / j)); + if (b >= D[Ma])i[xb](b >= D[oa] ? 0 : j * W(i[jb]() / j)); + if (b >= D[oa])i[kb](b >= D[Na] ? 1 : j * W(i[Oa]() / j)); + b >= D[Na] && (i[yb](b >= D[ta] ? 0 : j * W(i[$a]() / j)), h = i[ab]()); + b >= D[ta] && (h -= h % j, i[zb](h)); + if (b === D[Za])i[kb](i[Oa]() - i[lb]() + o(d, 1)); + d = 1; + h = i[ab](); + for (var k = i.getTime(), l = i[$a](), m = i[Oa](), i = g ? 0 : (864E5 + i.getTimezoneOffset() * 6E4) % 864E5; k < c;)e.push(k), b === D[ta] ? k = bb(h + d * j, 0) : b === D[Na] ? k = bb(h, l + d * j) : !g && (b === D[oa] || b === D[Za]) ? k = bb(h, l, m + d * j * (b === D[oa] ? 1 : 7)) : (k += b * j, b <= D[Ma] && k % D[oa] === i && (f[k] = oa)), d++; + e.push(k); + e.info = + u(a, {higherRanks: f, totalRange: b * j}); + return e + } + + function Ab() { + this.symbol = this.color = 0 + } + + function Qb(a, b) { + var c = a.length, d, e; + for (e = 0; e < c; e++)a[e].ss_i = e; + a.sort(function (a, c) { + d = b(a, c); + return d === 0 ? a.ss_i - c.ss_i : d + }); + for (e = 0; e < c; e++)delete a[e].ss_i + } + + function Pa(a) { + for (var b = a.length, c = a[0]; b--;)a[b] < c && (c = a[b]); + return c + } + + function Aa(a) { + for (var b = a.length, c = a[0]; b--;)a[b] > c && (c = a[b]); + return c + } + + function Ba(a, b) { + for (var c in a)a[c] && a[c] !== b && a[c].destroy && a[c].destroy(), delete a[c] + } + + function Qa(a) { + cb || (cb = S(ia)); + a && cb.appendChild(a); + cb.innerHTML = "" + } + + function mb(a, b) { + var c = "Highcharts error #" + a + ": www.highcharts.com/errors/" + a; + if (b)throw c; else N.console && console.log(c) + } + + function ja(a) { + return parseFloat(a.toPrecision(14)) + } + + function ua(a, b) { + Ra = o(a, b.animation) + } + + function Bb() { + var a = V.global.useUTC, b = a ? "getUTC" : "get", c = a ? "setUTC" : "set"; + bb = a ? Date.UTC : function (a, b, c, g, h, i) { + return(new Date(a, b, o(c, 1), o(g, 0), o(h, 0), o(i, 0))).getTime() + }; + ib = b + "Minutes"; + jb = b + "Hours"; + lb = b + "Day"; + Oa = b + "Date"; + $a = b + "Month"; + ab = b + "FullYear"; + wb = + c + "Minutes"; + xb = c + "Hours"; + kb = c + "Date"; + yb = c + "Month"; + zb = c + "FullYear" + } + + function va() { + } + + function Sa(a, b, c) { + this.axis = a; + this.pos = b; + this.type = c || ""; + this.isNew = !0; + c || this.addLabel() + } + + function nb(a, b) { + this.axis = a; + if (b)this.options = b, this.id = b.id; + return this + } + + function Cb(a, b, c, d, e) { + var f = a.chart.inverted; + this.axis = a; + this.isNegative = c; + this.options = b; + this.x = d; + this.stack = e; + this.alignOptions = {align: b.align || (f ? c ? "left" : "right" : "center"), verticalAlign: b.verticalAlign || (f ? "middle" : c ? "bottom" : "top"), y: o(b.y, f ? 4 : c ? 14 : + -6), x: o(b.x, f ? c ? -6 : 6 : 0)}; + this.textAlign = b.textAlign || (f ? c ? "right" : "left" : "center") + } + + function ob() { + this.init.apply(this, arguments) + } + + function pb(a, b) { + var c = b.borderWidth, d = b.style, e = b.shared, f = w(d.padding); + this.chart = a; + this.options = b; + d.padding = 0; + this.crosshairs = []; + this.currentY = this.currentX = 0; + this.tooltipIsHidden = !0; + this.label = a.renderer.label("", 0, 0, null, null, null, b.useHTML, null, "tooltip").attr({padding: f, fill: b.backgroundColor, "stroke-width": c, r: b.borderRadius, zIndex: 8}).css(d).hide().add(); + ga || this.label.shadow(b.shadow); + this.shared = e + } + + function Db(a, b) { + var c = ga ? "" : b.chart.zoomType; + this.zoomX = /x/.test(c); + this.zoomY = /y/.test(c); + this.options = b; + this.chart = a; + this.init(a, b.tooltip) + } + + function qb(a) { + this.init(a) + } + + function rb(a, b) { + var c, d = a.series; + a.series = null; + c = C(V, a); + c.series = a.series = d; + var d = c.chart, e = d.margin, e = aa(e) ? e : [e, e, e, e]; + this.optionsMarginTop = o(d.marginTop, e[0]); + this.optionsMarginRight = o(d.marginRight, e[1]); + this.optionsMarginBottom = o(d.marginBottom, e[2]); + this.optionsMarginLeft = o(d.marginLeft, e[3]); + this.runChartClick = + (e = d.events) && !!e.click; + this.callback = b; + this.isResizing = 0; + this.options = c; + this.axes = []; + this.series = []; + this.hasCartesianSeries = d.showAxes; + this.init(e) + } + + var A, B = document, N = window, L = Math, t = L.round, W = L.floor, wa = L.ceil, x = L.max, O = L.min, M = L.abs, X = L.cos, da = L.sin, xa = L.PI, Eb = xa * 2 / 360, ya = navigator.userAgent, La = /msie/i.test(ya) && !N.opera, Ca = B.documentMode === 8, Fb = /AppleWebKit/.test(ya), Gb = /Firefox/.test(ya), Da = !!B.createElementNS && !!B.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGRect, Rb = Gb && parseInt(ya.split("Firefox/")[1], + 10) < 4, ga = !Da && !La && !!B.createElement("canvas").getContext, Ta, ea = B.documentElement.ontouchstart !== A, Hb = {}, sb = 0, cb, V, db, Ra, Ua, D, Sb = function () { + }, ia = "div", U = "none", tb = "rgba(192,192,192," + (Da ? 1.0E-6 : 0.0020) + ")", vb = "millisecond", hb = "second", Ya = "minute", Ma = "hour", oa = "day", Za = "week", Na = "month", ta = "year", bb, ib, jb, lb, Oa, $a, ab, wb, xb, kb, yb, zb, Y = {}; + N.Highcharts = {}; + db = function (a, b, c) { + if (!s(b) || isNaN(b))return"Invalid date"; + var a = o(a, "%Y-%m-%d %H:%M:%S"), d = new Date(b), e, f = d[jb](), g = d[lb](), h = d[Oa](), i = d[$a](), j = + d[ab](), k = V.lang, l = k.weekdays, b = {a: l[g].substr(0, 3), A: l[g], d: sa(h), e: h, b: k.shortMonths[i], B: k.months[i], m: sa(i + 1), y: j.toString().substr(2, 2), Y: j, H: sa(f), I: sa(f % 12 || 12), l: f % 12 || 12, M: sa(d[ib]()), p: f < 12 ? "AM" : "PM", P: f < 12 ? "am" : "pm", S: sa(d.getSeconds()), L: sa(t(b % 1E3), 3)}; + for (e in b)a = a.replace("%" + e, b[e]); + return c ? a.substr(0, 1).toUpperCase() + a.substr(1) : a + }; + Ab.prototype = {wrapColor: function (a) { + if (this.color >= a)this.color = 0 + }, wrapSymbol: function (a) { + if (this.symbol >= a)this.symbol = 0 + }}; + D = la(vb, 1, hb, 1E3, Ya, 6E4, + Ma, 36E5, oa, 864E5, Za, 6048E5, Na, 2592E6, ta, 31556952E3); + Ua = {init: function (a, b, c) { + var b = b || "", d = a.shift, e = b.indexOf("C") > -1, f = e ? 7 : 3, g, b = b.split(" "), c = [].concat(c), h, i, j = function (a) { + for (g = a.length; g--;)a[g] === "M" && a.splice(g + 1, 0, a[g + 1], a[g + 2], a[g + 1], a[g + 2]) + }; + e && (j(b), j(c)); + a.isArea && (h = b.splice(b.length - 6, 6), i = c.splice(c.length - 6, 6)); + if (d <= c.length / f)for (; d--;)c = [].concat(c).splice(0, f).concat(c); + a.shift = 0; + if (b.length)for (a = c.length; b.length < a;)d = [].concat(b).splice(b.length - f, f), e && (d[f - 6] = d[f - 2], d[f - + 5] = d[f - 1]), b = b.concat(d); + h && (b = b.concat(h), c = c.concat(i)); + return[b, c] + }, step: function (a, b, c, d) { + var e = [], f = a.length; + if (c === 1)e = d; else if (f === b.length && c < 1)for (; f--;)d = parseFloat(a[f]), e[f] = isNaN(d) ? a[f] : c * parseFloat(b[f] - d) + d; else e = b; + return e + }}; + var T = N.HighchartsAdapter, G = T || {}, Va = G.adapterRun, Ib = G.getScript, n = G.each, ub = G.grep, Jb = G.offset, Ea = G.map, C = G.merge, I = G.addEvent, P = G.removeEvent, E = G.fireEvent, Kb = G.washMouseEvent, eb = G.animate, Fa = G.stop; + T && T.init && T.init(Ua); + if (!T && N.jQuery) { + var Q = jQuery, Ib = Q.getScript, + Va = function (a, b) { + return Q(a)[b]() + }, n = function (a, b) { + for (var c = 0, d = a.length; c < d; c++)if (b.call(a[c], a[c], c, a) === !1)return c + }, ub = Q.grep, Ea = function (a, b) { + for (var c = [], d = 0, e = a.length; d < e; d++)c[d] = b.call(a[d], a[d], d, a); + return c + }, C = function () { + var a = arguments; + return Q.extend(!0, null, a[0], a[1], a[2], a[3]) + }, Jb = function (a) { + return Q(a).offset() + }, I = function (a, b, c) { + Q(a).bind(b, c) + }, P = function (a, b, c) { + var d = B.removeEventListener ? "removeEventListener" : "detachEvent"; + B[d] && !a[d] && (a[d] = function () { + }); + Q(a).unbind(b, c) + }, + E = function (a, b, c, d) { + var e = Q.Event(b), f = "detached" + b, g; + !La && c && (delete c.layerX, delete c.layerY); + u(e, c); + a[b] && (a[f] = a[b], a[b] = null); + n(["preventDefault", "stopPropagation"], function (a) { + var b = e[a]; + e[a] = function () { + try { + b.call(e) + } catch (c) { + a === "preventDefault" && (g = !0) + } + } + }); + Q(a).trigger(e); + a[f] && (a[b] = a[f], a[f] = null); + d && !e.isDefaultPrevented() && !g && d(e) + }, Kb = function (a) { + return a + }, eb = function (a, b, c) { + var d = Q(a); + if (b.d)a.toD = b.d, b.d = 1; + d.stop(); + d.animate(b, c) + }, Fa = function (a) { + Q(a).stop() + }; + Q.extend(Q.easing, {easeOutQuad: function (a, b, c, d, e) { + return-d * (b /= e) * (b - 2) + c + }}); + var Lb = Q.fx, Mb = Lb.step; + n(["cur", "_default", "width", "height"], function (a, b) { + var c = Mb, d, e; + a === "cur" ? c = Lb.prototype : a === "_default" && Q.Tween && (c = Q.Tween.propHooks[a], a = "set"); + (d = c[a]) && (c[a] = function (c) { + c = b ? c : this; + e = c.elem; + return e.attr ? e.attr(c.prop, a === "cur" ? A : c.now) : d.apply(this, arguments) + }) + }); + Mb.d = function (a) { + var b = a.elem; + if (!a.started) { + var c = Ua.init(b, b.d, b.toD); + a.start = c[0]; + a.end = c[1]; + a.started = !0 + } + b.attr("d", Ua.step(a.start, a.end, a.pos, b.toD)) + } + } + G = {enabled: !0, + align: "center", x: 0, y: 15, style: {color: "#666", fontSize: "11px", lineHeight: "14px"}}; + V = {colors: "#4572A7,#AA4643,#89A54E,#80699B,#3D96AE,#DB843D,#92A8CD,#A47D7C,#B5CA92".split(","), symbols: ["circle", "diamond", "square", "triangle", "triangle-down"], lang: {loading: "Loading...", months: "January,February,March,April,May,June,July,August,September,October,November,December".split(","), shortMonths: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","), weekdays: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","), + decimalPoint: ".", resetZoom: "Reset zoom", resetZoomTitle: "Reset zoom level 1:1", thousandsSep: ","}, global: {useUTC: !0, canvasToolsURL: "http://code.highcharts.com/2.2.5/modules/canvas-tools.js"}, chart: {borderColor: "#4572A7", borderRadius: 5, defaultSeriesType: "line", ignoreHiddenSeries: !0, spacingTop: 10, spacingRight: 10, spacingBottom: 15, spacingLeft: 10, style: {fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', fontSize: "12px"}, backgroundColor: "#FFFFFF", plotBorderColor: "#C0C0C0", + resetZoomButton: {theme: {zIndex: 20}, position: {align: "right", x: -10, y: 10}}}, title: {text: "Chart title", align: "center", y: 15, style: {color: "#3E576F", fontSize: "16px"}}, subtitle: {text: "", align: "center", y: 30, style: {color: "#6D869F"}}, plotOptions: {line: {allowPointSelect: !1, showCheckbox: !1, animation: {duration: 1E3}, events: {}, lineWidth: 2, shadow: !0, marker: {enabled: !0, lineWidth: 0, radius: 4, lineColor: "#FFFFFF", states: {hover: {}, select: {fillColor: "#FFFFFF", lineColor: "#000000", lineWidth: 2}}}, point: {events: {}}, dataLabels: C(G, + {enabled: !1, y: -6, formatter: function () { + return this.y + }}), cropThreshold: 300, pointRange: 0, showInLegend: !0, states: {hover: {marker: {}}, select: {marker: {}}}, stickyTracking: !0}}, labels: {style: {position: "absolute", color: "#3E576F"}}, legend: {enabled: !0, align: "center", layout: "horizontal", labelFormatter: function () { + return this.name + }, borderWidth: 1, borderColor: "#909090", borderRadius: 5, navigation: {activeColor: "#3E576F", inactiveColor: "#CCC"}, shadow: !1, itemStyle: {cursor: "pointer", color: "#3E576F", fontSize: "12px"}, itemHoverStyle: {color: "#000"}, + itemHiddenStyle: {color: "#CCC"}, itemCheckboxStyle: {position: "absolute", width: "13px", height: "13px"}, symbolWidth: 16, symbolPadding: 5, verticalAlign: "bottom", x: 0, y: 0}, loading: {labelStyle: {fontWeight: "bold", position: "relative", top: "1em"}, style: {position: "absolute", backgroundColor: "white", opacity: 0.5, textAlign: "center"}}, tooltip: {enabled: !0, backgroundColor: "rgba(255, 255, 255, .85)", borderWidth: 2, borderRadius: 5, dateTimeLabelFormats: {millisecond: "%A, %b %e, %H:%M:%S.%L", second: "%A, %b %e, %H:%M:%S", minute: "%A, %b %e, %H:%M", + hour: "%A, %b %e, %H:%M", day: "%A, %b %e, %Y", week: "Week from %A, %b %e, %Y", month: "%B %Y", year: "%Y"}, headerFormat: '{point.key}
        ', pointFormat: '{series.name}: {point.y}
        ', shadow: !0, shared: ga, snap: ea ? 25 : 10, style: {color: "#333333", fontSize: "12px", padding: "5px", whiteSpace: "nowrap"}}, credits: {enabled: !0, text: "Highcharts.com", href: "http://www.highcharts.com", position: {align: "right", x: -10, verticalAlign: "bottom", y: -5}, + style: {cursor: "pointer", color: "#909090", fontSize: "10px"}}}; + var Z = V.plotOptions, T = Z.line; + Bb(); + var pa = function (a) { + var b = [], c; + (function (a) { + (c = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(a)) ? b = [w(c[1]), w(c[2]), w(c[3]), parseFloat(c[4], 10)] : (c = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(a)) && (b = [w(c[1], 16), w(c[2], 16), w(c[3], 16), 1]) + })(a); + return{get: function (c) { + return b && !isNaN(b[0]) ? c === "rgb" ? "rgb(" + b[0] + "," + b[1] + "," + b[2] + ")" : c === "a" ? b[3] : + "rgba(" + b.join(",") + ")" : a + }, brighten: function (a) { + if (Ka(a) && a !== 0) { + var c; + for (c = 0; c < 3; c++)b[c] += w(a * 255), b[c] < 0 && (b[c] = 0), b[c] > 255 && (b[c] = 255) + } + return this + }, setOpacity: function (a) { + b[3] = a; + return this + }} + }; + va.prototype = {init: function (a, b) { + this.element = b === "span" ? S(b) : B.createElementNS("http://www.w3.org/2000/svg", b); + this.renderer = a; + this.attrSetters = {} + }, animate: function (a, b, c) { + b = o(b, Ra, !0); + Fa(this); + if (b) { + b = C(b); + if (c)b.complete = c; + eb(this, a, b) + } else this.attr(a), c && c() + }, attr: function (a, b) { + var c, d, e, f, g = this.element, + h = g.nodeName, i = this.renderer, j, k = this.attrSetters, l = this.shadows, m, p, q = this; + ra(a) && s(b) && (c = a, a = {}, a[c] = b); + if (ra(a))c = a, h === "circle" ? c = {x: "cx", y: "cy"}[c] || c : c === "strokeWidth" && (c = "stroke-width"), q = z(g, c) || this[c] || 0, c !== "d" && c !== "visibility" && (q = parseFloat(q)); else for (c in a)if (j = !1, d = a[c], e = k[c] && k[c](d, c), e !== !1) { + e !== A && (d = e); + if (c === "d")d && d.join && (d = d.join(" ")), /(NaN| {2}|^$)/.test(d) && (d = "M 0 0"); else if (c === "x" && h === "text") { + for (e = 0; e < g.childNodes.length; e++)f = g.childNodes[e], z(f, "x") === z(g, + "x") && z(f, "x", d); + this.rotation && z(g, "transform", "rotate(" + this.rotation + " " + d + " " + w(a.y || z(g, "y")) + ")") + } else if (c === "fill")d = i.color(d, g, c); else if (h === "circle" && (c === "x" || c === "y"))c = {x: "cx", y: "cy"}[c] || c; else if (h === "rect" && c === "r")z(g, {rx: d, ry: d}), j = !0; else if (c === "translateX" || c === "translateY" || c === "rotation" || c === "verticalAlign")j = p = !0; else if (c === "stroke")d = i.color(d, g, c); else if (c === "dashstyle")if (c = "stroke-dasharray", d = d && d.toLowerCase(), d === "solid")d = U; else { + if (d) { + d = d.replace("shortdashdotdot", + "3,1,1,1,1,1,").replace("shortdashdot", "3,1,1,1").replace("shortdot", "1,1,").replace("shortdash", "3,1,").replace("longdash", "8,3,").replace(/dot/g, "1,3,").replace("dash", "4,3,").replace(/,$/, "").split(","); + for (e = d.length; e--;)d[e] = w(d[e]) * a["stroke-width"]; + d = d.join(",") + } + } else if (c === "isTracker")this[c] = d; else if (c === "width")d = w(d); else if (c === "align")c = "text-anchor", d = {left: "start", center: "middle", right: "end"}[d]; else if (c === "title")e = g.getElementsByTagName("title")[0], e || (e = B.createElementNS("http://www.w3.org/2000/svg", + "title"), g.appendChild(e)), e.textContent = d; + c === "strokeWidth" && (c = "stroke-width"); + Fb && c === "stroke-width" && d === 0 && (d = 1.0E-6); + this.symbolName && /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(c) && (m || (this.symbolAttr(a), m = !0), j = !0); + if (l && /^(width|height|visibility|x|y|d|transform)$/.test(c))for (e = l.length; e--;)z(l[e], c, c === "height" ? x(d - (l[e].cutHeight || 0), 0) : d); + if ((c === "width" || c === "height") && h === "rect" && d < 0)d = 0; + this[c] = d; + p && this.updateTransform(); + c === "text" ? (this.textStr = d, this.added && + i.buildText(this)) : j || z(g, c, d) + } + if (Fb && /Chrome\/(18|19)/.test(ya) && h === "text" && (a.x !== A || a.y !== A))c = g.parentNode, d = g.nextSibling, c && (c.removeChild(g), d ? c.insertBefore(g, d) : c.appendChild(g)); + return q + }, symbolAttr: function (a) { + var b = this; + n("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","), function (c) { + b[c] = o(a[c], b[c]) + }); + b.attr({d: b.renderer.symbols[b.symbolName](b.x, b.y, b.width, b.height, b)}) + }, clip: function (a) { + return this.attr("clip-path", "url(" + this.renderer.url + "#" + a.id + ")") + }, crisp: function (a, b, c, d, e) { + var f, g = {}, h = {}, i, a = a || this.strokeWidth || this.attr && this.attr("stroke-width") || 0; + i = t(a) % 2 / 2; + h.x = W(b || this.x || 0) + i; + h.y = W(c || this.y || 0) + i; + h.width = W((d || this.width || 0) - 2 * i); + h.height = W((e || this.height || 0) - 2 * i); + h.strokeWidth = a; + for (f in h)this[f] !== h[f] && (this[f] = g[f] = h[f]); + return g + }, css: function (a) { + var b = this.element, b = a && a.width && b.nodeName === "text", c, d = "", e = function (a, b) { + return"-" + b.toLowerCase() + }; + if (a && a.color)a.fill = a.color; + this.styles = a = u(this.styles, a); + if (La && !Da)b && delete a.width, F(this.element, + a); else { + for (c in a)d += c.replace(/([A-Z])/g, e) + ":" + a[c] + ";"; + this.attr({style: d}) + } + b && this.added && this.renderer.buildText(this); + return this + }, on: function (a, b) { + var c = b; + ea && a === "click" && (a = "touchstart", c = function (a) { + a.preventDefault(); + b() + }); + this.element["on" + a] = c; + return this + }, setRadialReference: function (a) { + this.element.radialReference = a; + return this + }, translate: function (a, b) { + return this.attr({translateX: a, translateY: b}) + }, invert: function () { + this.inverted = !0; + this.updateTransform(); + return this + }, htmlCss: function (a) { + var b = + this.element; + if (b = a && b.tagName === "SPAN" && a.width)delete a.width, this.textWidth = b, this.updateTransform(); + this.styles = u(this.styles, a); + F(this.element, a); + return this + }, htmlGetBBox: function (a) { + var b = this.element, c = this.bBox; + if (!c || a) { + if (b.nodeName === "text")b.style.position = "absolute"; + c = this.bBox = {x: b.offsetLeft, y: b.offsetTop, width: b.offsetWidth, height: b.offsetHeight} + } + return c + }, htmlUpdateTransform: function () { + if (this.added) { + var a = this.renderer, b = this.element, c = this.translateX || 0, d = this.translateY || 0, e = this.x || + 0, f = this.y || 0, g = this.textAlign || "left", h = {left: 0, center: 0.5, right: 1}[g], i = g && g !== "left", j = this.shadows; + if (c || d)F(b, {marginLeft: c, marginTop: d}), j && n(j, function (a) { + F(a, {marginLeft: c + 1, marginTop: d + 1}) + }); + this.inverted && n(b.childNodes, function (c) { + a.invertChild(c, b) + }); + if (b.tagName === "SPAN") { + var k, l, j = this.rotation, m; + k = 0; + var p = 1, q = 0, fa; + m = w(this.textWidth); + var r = this.xCorr || 0, y = this.yCorr || 0, $ = [j, g, b.innerHTML, this.textWidth].join(","); + if ($ !== this.cTT)s(j) && (k = j * Eb, p = X(k), q = da(k), F(b, {filter: j ? ["progid:DXImageTransform.Microsoft.Matrix(M11=", + p, ", M12=", -q, ", M21=", q, ", M22=", p, ", sizingMethod='auto expand')"].join("") : U})), k = o(this.elemWidth, b.offsetWidth), l = o(this.elemHeight, b.offsetHeight), k > m && /[ \-]/.test(b.innerText) && (F(b, {width: m + "px", display: "block", whiteSpace: "normal"}), k = m), m = a.fontMetrics(b.style.fontSize).b, r = p < 0 && -k, y = q < 0 && -l, fa = p * q < 0, r += q * m * (fa ? 1 - h : h), y -= p * m * (j ? fa ? h : 1 - h : 1), i && (r -= k * h * (p < 0 ? -1 : 1), j && (y -= l * h * (q < 0 ? -1 : 1)), F(b, {textAlign: g})), this.xCorr = r, this.yCorr = y; + F(b, {left: e + r + "px", top: f + y + "px"}); + this.cTT = $ + } + } else this.alignOnAdd = !0 + }, updateTransform: function () { + var a = this.translateX || 0, b = this.translateY || 0, c = this.inverted, d = this.rotation, e = []; + c && (a += this.attr("width"), b += this.attr("height")); + (a || b) && e.push("translate(" + a + "," + b + ")"); + c ? e.push("rotate(90) scale(-1,1)") : d && e.push("rotate(" + d + " " + (this.x || 0) + " " + (this.y || 0) + ")"); + e.length && z(this.element, "transform", e.join(" ")) + }, toFront: function () { + var a = this.element; + a.parentNode.appendChild(a); + return this + }, align: function (a, b, c) { + a ? (this.alignOptions = a, this.alignByTranslate = b, c || + this.renderer.alignedObjects.push(this)) : (a = this.alignOptions, b = this.alignByTranslate); + var c = o(c, this.renderer), d = a.align, e = a.verticalAlign, f = (c.x || 0) + (a.x || 0), g = (c.y || 0) + (a.y || 0), h = {}; + /^(right|center)$/.test(d) && (f += (c.width - (a.width || 0)) / {right: 1, center: 2}[d]); + h[b ? "translateX" : "x"] = t(f); + /^(bottom|middle)$/.test(e) && (g += (c.height - (a.height || 0)) / ({bottom: 1, middle: 2}[e] || 1)); + h[b ? "translateY" : "y"] = t(g); + this[this.placed ? "animate" : "attr"](h); + this.placed = !0; + this.alignAttr = h; + return this + }, getBBox: function (a) { + var b, + c, d = this.rotation; + c = this.element; + var e = d * Eb; + if (c.namespaceURI === "http://www.w3.org/2000/svg" || this.renderer.forExport) { + try { + b = c.getBBox ? u({}, c.getBBox()) : {width: c.offsetWidth, height: c.offsetHeight} + } catch (f) { + } + if (!b || b.width < 0)b = {width: 0, height: 0}; + a = b.width; + c = b.height; + if (d)b.width = M(c * da(e)) + M(a * X(e)), b.height = M(c * X(e)) + M(a * da(e)) + } else b = this.htmlGetBBox(a); + return b + }, show: function () { + return this.attr({visibility: "visible"}) + }, hide: function () { + return this.attr({visibility: "hidden"}) + }, add: function (a) { + var b = + this.renderer, c = a || b, d = c.element || b.box, e = d.childNodes, f = this.element, g = z(f, "zIndex"), h; + this.parentInverted = a && a.inverted; + this.textStr !== void 0 && b.buildText(this); + if (g)c.handleZ = !0, g = w(g); + if (c.handleZ)for (c = 0; c < e.length; c++)if (a = e[c], b = z(a, "zIndex"), a !== f && (w(b) > g || !s(g) && s(b))) { + d.insertBefore(f, a); + h = !0; + break + } + h || d.appendChild(f); + this.added = !0; + E(this, "add"); + return this + }, safeRemoveChild: function (a) { + var b = a.parentNode; + b && b.removeChild(a) + }, destroy: function () { + var a = this, b = a.element || {}, c = a.shadows, d = a.box, + e, f; + b.onclick = b.onmouseout = b.onmouseover = b.onmousemove = null; + Fa(a); + if (a.clipPath)a.clipPath = a.clipPath.destroy(); + if (a.stops) { + for (f = 0; f < a.stops.length; f++)a.stops[f] = a.stops[f].destroy(); + a.stops = null + } + a.safeRemoveChild(b); + c && n(c, function (b) { + a.safeRemoveChild(b) + }); + d && d.destroy(); + za(a.renderer.alignedObjects, a); + for (e in a)delete a[e]; + return null + }, empty: function () { + for (var a = this.element, b = a.childNodes, c = b.length; c--;)a.removeChild(b[c]) + }, shadow: function (a, b, c) { + var d = [], e, f = this.element, g, h = this.parentInverted ? + "(-1,-1)" : "(1,1)"; + if (a) { + for (a = 1; a <= 3; a++) { + e = f.cloneNode(0); + g = 7 - 2 * a; + z(e, {isShadow: "true", stroke: "rgb(0, 0, 0)", "stroke-opacity": 0.05 * a, "stroke-width": g, transform: "translate" + h, fill: U}); + if (c)z(e, "height", x(z(e, "height") - g, 0)), e.cutHeight = g; + b ? b.element.appendChild(e) : f.parentNode.insertBefore(e, f); + d.push(e) + } + this.shadows = d + } + return this + }}; + var qa = function () { + this.init.apply(this, arguments) + }; + qa.prototype = {Element: va, init: function (a, b, c, d) { + var e = location, f; + f = this.createElement("svg").attr({xmlns: "http://www.w3.org/2000/svg", + version: "1.1"}); + a.appendChild(f.element); + this.isSVG = !0; + this.box = f.element; + this.boxWrapper = f; + this.alignedObjects = []; + this.url = La ? "" : e.href.replace(/#.*?$/, "").replace(/([\('\)])/g, "\\$1"); + this.defs = this.createElement("defs").add(); + this.forExport = d; + this.gradients = {}; + this.setSize(b, c, !1); + var g; + if (Gb && a.getBoundingClientRect)this.subPixelFix = b = function () { + F(a, {left: 0, top: 0}); + g = a.getBoundingClientRect(); + F(a, {left: wa(g.left) - g.left + "px", top: wa(g.top) - g.top + "px"}) + }, b(), I(N, "resize", b) + }, isHidden: function () { + return!this.boxWrapper.getBBox().width + }, + destroy: function () { + var a = this.defs; + this.box = null; + this.boxWrapper = this.boxWrapper.destroy(); + Ba(this.gradients || {}); + this.gradients = null; + if (a)this.defs = a.destroy(); + this.subPixelFix && P(N, "resize", this.subPixelFix); + return this.alignedObjects = null + }, createElement: function (a) { + var b = new this.Element; + b.init(this, a); + return b + }, draw: function () { + }, buildText: function (a) { + for (var b = a.element, c = o(a.textStr, "").toString().replace(/<(b|strong)>/g, '').replace(/<(i|em)>/g, '').replace(//g, "").split(//g), d = b.childNodes, e = /style="([^"]+)"/, f = /href="([^"]+)"/, g = z(b, "x"), h = a.styles, i = h && w(h.width), j = h && h.lineHeight, k, h = d.length, l = []; h--;)b.removeChild(d[h]); + i && !a.added && this.box.appendChild(b); + c[c.length - 1] === "" && c.pop(); + n(c, function (c, d) { + var h, fa = 0, r, c = c.replace(//g, "|||"); + h = c.split("|||"); + n(h, function (c) { + if (c !== "" || h.length === 1) { + var m = {}, n = B.createElementNS("http://www.w3.org/2000/svg", + "tspan"); + e.test(c) && z(n, "style", c.match(e)[1].replace(/(;| |^)color([ :])/, "$1fill$2")); + f.test(c) && (z(n, "onclick", 'location.href="' + c.match(f)[1] + '"'), F(n, {cursor: "pointer"})); + c = (c.replace(/<(.|\n)*?>/g, "") || " ").replace(/</g, "<").replace(/>/g, ">"); + n.appendChild(B.createTextNode(c)); + fa ? m.dx = 3 : m.x = g; + if (!fa) { + if (d) { + !Da && a.renderer.forExport && F(n, {display: "block"}); + r = N.getComputedStyle && w(N.getComputedStyle(k, null).getPropertyValue("line-height")); + if (!r || isNaN(r)) { + var o; + if (!(o = j))if (!(o = k.offsetHeight))l[d] = + b.getBBox().height, o = t(l[d] - (l[d - 1] || 0)) || 18; + r = o + } + z(n, "dy", r) + } + k = n + } + z(n, m); + b.appendChild(n); + fa++; + if (i)for (var c = c.replace(/-/g, "- ").split(" "), H = []; c.length || H.length;)o = a.getBBox().width, m = o > i, !m || c.length === 1 ? (c = H, H = [], c.length && (n = B.createElementNS("http://www.w3.org/2000/svg", "tspan"), z(n, {dy: j || 16, x: g}), b.appendChild(n), o > i && (i = o))) : (n.removeChild(n.firstChild), H.unshift(c.pop())), c.length && n.appendChild(B.createTextNode(c.join(" ").replace(/- /g, "-"))) + } + }) + }) + }, button: function (a, b, c, d, e, f, g) { + var h = + this.label(a, b, c), i = 0, j, k, l, m, p, a = {x1: 0, y1: 0, x2: 0, y2: 1}, e = C(la("stroke-width", 1, "stroke", "#999", "fill", la("linearGradient", a, "stops", [ + [0, "#FFF"], + [1, "#DDD"] + ]), "r", 3, "padding", 3, "style", la("color", "black")), e); + l = e.style; + delete e.style; + f = C(e, la("stroke", "#68A", "fill", la("linearGradient", a, "stops", [ + [0, "#FFF"], + [1, "#ACF"] + ])), f); + m = f.style; + delete f.style; + g = C(e, la("stroke", "#68A", "fill", la("linearGradient", a, "stops", [ + [0, "#9BD"], + [1, "#CDF"] + ])), g); + p = g.style; + delete g.style; + I(h.element, "mouseenter", function () { + h.attr(f).css(m) + }); + I(h.element, "mouseleave", function () { + j = [e, f, g][i]; + k = [l, m, p][i]; + h.attr(j).css(k) + }); + h.setState = function (a) { + (i = a) ? a === 2 && h.attr(g).css(p) : h.attr(e).css(l) + }; + return h.on("click",function () { + d.call(h) + }).attr(e).css(u({cursor: "default"}, l)) + }, crispLine: function (a, b) { + a[1] === a[4] && (a[1] = a[4] = t(a[1]) + b % 2 / 2); + a[2] === a[5] && (a[2] = a[5] = t(a[2]) + b % 2 / 2); + return a + }, path: function (a) { + var b = {fill: U}; + Ja(a) ? b.d = a : aa(a) && u(b, a); + return this.createElement("path").attr(b) + }, circle: function (a, b, c) { + a = aa(a) ? a : {x: a, y: b, r: c}; + return this.createElement("circle").attr(a) + }, + arc: function (a, b, c, d, e, f) { + if (aa(a))b = a.y, c = a.r, d = a.innerR, e = a.start, f = a.end, a = a.x; + return this.symbol("arc", a || 0, b || 0, c || 0, c || 0, {innerR: d || 0, start: e || 0, end: f || 0}) + }, rect: function (a, b, c, d, e, f) { + e = aa(a) ? a.r : e; + e = this.createElement("rect").attr({rx: e, ry: e, fill: U}); + return e.attr(aa(a) ? a : e.crisp(f, a, b, x(c, 0), x(d, 0))) + }, setSize: function (a, b, c) { + var d = this.alignedObjects, e = d.length; + this.width = a; + this.height = b; + for (this.boxWrapper[o(c, !0) ? "animate" : "attr"]({width: a, height: b}); e--;)d[e].align() + }, g: function (a) { + var b = + this.createElement("g"); + return s(a) ? b.attr({"class": "highcharts-" + a}) : b + }, image: function (a, b, c, d, e) { + var f = {preserveAspectRatio: U}; + arguments.length > 1 && u(f, {x: b, y: c, width: d, height: e}); + f = this.createElement("image").attr(f); + f.element.setAttributeNS ? f.element.setAttributeNS("http://www.w3.org/1999/xlink", "href", a) : f.element.setAttribute("hc-svg-href", a); + return f + }, symbol: function (a, b, c, d, e, f) { + var g, h = this.symbols[a], h = h && h(t(b), t(c), d, e, f), i = /^url\((.*?)\)$/, j, k; + h ? (g = this.path(h), u(g, {symbolName: a, x: b, y: c, + width: d, height: e}), f && u(g, f)) : i.test(a) && (k = function (a, b) { + a.attr({width: b[0], height: b[1]}); + a.alignByTranslate || a.translate(-t(b[0] / 2), -t(b[1] / 2)) + }, j = a.match(i)[1], a = Hb[j], g = this.image(j).attr({x: b, y: c}), a ? k(g, a) : (g.attr({width: 0, height: 0}), S("img", {onload: function () { + k(g, Hb[j] = [this.width, this.height]) + }, src: j}))); + return g + }, symbols: {circle: function (a, b, c, d) { + var e = 0.166 * c; + return["M", a + c / 2, b, "C", a + c + e, b, a + c + e, b + d, a + c / 2, b + d, "C", a - e, b + d, a - e, b, a + c / 2, b, "Z"] + }, square: function (a, b, c, d) { + return["M", a, b, "L", a + + c, b, a + c, b + d, a, b + d, "Z"] + }, triangle: function (a, b, c, d) { + return["M", a + c / 2, b, "L", a + c, b + d, a, b + d, "Z"] + }, "triangle-down": function (a, b, c, d) { + return["M", a, b, "L", a + c, b, a + c / 2, b + d, "Z"] + }, diamond: function (a, b, c, d) { + return["M", a + c / 2, b, "L", a + c, b + d / 2, a + c / 2, b + d, a, b + d / 2, "Z"] + }, arc: function (a, b, c, d, e) { + var f = e.start, c = e.r || c || d, g = e.end - 1.0E-6, d = e.innerR, h = e.open, i = X(f), j = da(f), k = X(g), g = da(g), e = e.end - f < xa ? 0 : 1; + return["M", a + c * i, b + c * j, "A", c, c, 0, e, 1, a + c * k, b + c * g, h ? "M" : "L", a + d * k, b + d * g, "A", d, d, 0, e, 0, a + d * i, b + d * j, h ? "" : "Z"] + }}, clipRect: function (a, b, c, d) { + var e = "highcharts-" + sb++, f = this.createElement("clipPath").attr({id: e}).add(this.defs), a = this.rect(a, b, c, d, 0).add(f); + a.id = e; + a.clipPath = f; + return a + }, color: function (a, b, c) { + var d = this, e, f = /^rgba/, g; + a && a.linearGradient ? g = "linearGradient" : a && a.radialGradient && (g = "radialGradient"); + if (g) { + var c = a[g], h = d.gradients, i, j, k, b = b.radialReference; + if (!c.id || !h[c.id])Ja(c) && (a[g] = c = {x1: c[0], y1: c[1], x2: c[2], y2: c[3], gradientUnits: "userSpaceOnUse"}), g === "radialGradient" && b && !s(c.gradientUnits) && u(c, {cx: b[0] - b[2] / + 2 + c.cx * b[2], cy: b[1] - b[2] / 2 + c.cy * b[2], r: c.r * b[2], gradientUnits: "userSpaceOnUse"}), c.id = "highcharts-" + sb++, h[c.id] = i = d.createElement(g).attr(c).add(d.defs), i.stops = [], n(a.stops, function (a) { + f.test(a[1]) ? (e = pa(a[1]), j = e.get("rgb"), k = e.get("a")) : (j = a[1], k = 1); + a = d.createElement("stop").attr({offset: a[0], "stop-color": j, "stop-opacity": k}).add(i); + i.stops.push(a) + }); + return"url(" + d.url + "#" + c.id + ")" + } else return f.test(a) ? (e = pa(a), z(b, c + "-opacity", e.get("a")), e.get("rgb")) : (b.removeAttribute(c + "-opacity"), a) + }, text: function (a, b, c, d) { + var e = V.chart.style; + if (d && !this.forExport)return this.html(a, b, c); + b = t(o(b, 0)); + c = t(o(c, 0)); + a = this.createElement("text").attr({x: b, y: c, text: a}).css({fontFamily: e.fontFamily, fontSize: e.fontSize}); + a.x = b; + a.y = c; + return a + }, html: function (a, b, c) { + var d = V.chart.style, e = this.createElement("span"), f = e.attrSetters, g = e.element, h = e.renderer; + f.text = function (a) { + g.innerHTML = a; + return!1 + }; + f.x = f.y = f.align = function (a, b) { + b === "align" && (b = "textAlign"); + e[b] = a; + e.htmlUpdateTransform(); + return!1 + }; + e.attr({text: a, x: t(b), y: t(c)}).css({position: "absolute", + whiteSpace: "nowrap", fontFamily: d.fontFamily, fontSize: d.fontSize}); + e.css = e.htmlCss; + if (h.isSVG)e.add = function (a) { + var b, c, d = h.box.parentNode; + if (a) { + if (b = a.div, !b)b = a.div = S(ia, {className: z(a.element, "class")}, {position: "absolute", left: a.attr("translateX") + "px", top: a.attr("translateY") + "px"}, d), c = b.style, u(a.attrSetters, {translateX: function (a) { + c.left = a + "px" + }, translateY: function (a) { + c.top = a + "px" + }, visibility: function (a, b) { + c[b] = a + }}) + } else b = d; + b.appendChild(g); + e.added = !0; + e.alignOnAdd && e.htmlUpdateTransform(); + return e + }; + return e + }, fontMetrics: function (a) { + var a = w(a || 11), a = a < 24 ? a + 4 : t(a * 1.2), b = t(a * 0.8); + return{h: a, b: b} + }, label: function (a, b, c, d, e, f, g, h, i) { + function j() { + var a = p.styles, a = a && a.textAlign, b = $ * (1 - y), c; + c = h ? 0 : Ha; + if (s(Ga) && (a === "center" || a === "right"))b += {center: 0.5, right: 1}[a] * (Ga - r.width); + (b !== q.x || c !== q.y) && q.attr({x: b, y: c}); + q.x = b; + q.y = c + } + + function k(a, b) { + o ? o.attr(a, b) : x[a] = b + } + + function l() { + p.attr({text: a, x: b, y: c}); + s(e) && p.attr({anchorX: e, anchorY: f}) + } + + var m = this, p = m.g(i), q = m.text("", 0, 0, g).attr({zIndex: 1}).add(p), + o, r, y = 0, $ = 3, Ga, v, H, J, K = 0, x = {}, Ha, g = p.attrSetters; + I(p, "add", l); + g.width = function (a) { + Ga = a; + return!1 + }; + g.height = function (a) { + v = a; + return!1 + }; + g.padding = function (a) { + s(a) && a !== $ && ($ = a, j()); + return!1 + }; + g.align = function (a) { + y = {left: 0, center: 0.5, right: 1}[a]; + return!1 + }; + g.text = function (a, b) { + q.attr(b, a); + var c; + c = q.element.style; + r = (Ga === void 0 || v === void 0 || p.styles.textAlign) && q.getBBox(!0); + p.width = (Ga || r.width || 0) + 2 * $; + p.height = (v || r.height || 0) + 2 * $; + Ha = $ + m.fontMetrics(c && c.fontSize).b; + if (!o)c = h ? -Ha : 0, p.box = o = d ? m.symbol(d, + -y * $, c, p.width, p.height) : m.rect(-y * $, c, p.width, p.height, 0, x["stroke-width"]), o.add(p); + o.attr(C({width: p.width, height: p.height}, x)); + x = null; + j(); + return!1 + }; + g["stroke-width"] = function (a, b) { + K = a % 2 / 2; + k(b, a); + return!1 + }; + g.stroke = g.fill = g.r = function (a, b) { + k(b, a); + return!1 + }; + g.anchorX = function (a, b) { + e = a; + k(b, a + K - H); + return!1 + }; + g.anchorY = function (a, b) { + f = a; + k(b, a - J); + return!1 + }; + g.x = function (a) { + p.x = a; + a -= y * ((Ga || r.width) + $); + H = t(a); + p.attr("translateX", H); + return!1 + }; + g.y = function (a) { + J = p.y = t(a); + p.attr("translateY", a); + return!1 + }; + var w = p.css; + return u(p, {css: function (a) { + if (a) { + var b = {}, a = C({}, a); + n("fontSize,fontWeight,fontFamily,color,lineHeight,width".split(","), function (c) { + a[c] !== A && (b[c] = a[c], delete a[c]) + }); + q.css(b) + } + return w.call(p, a) + }, getBBox: function () { + return o.getBBox() + }, shadow: function (a) { + o.shadow(a); + return p + }, destroy: function () { + P(p, "add", l); + P(p.element, "mouseenter"); + P(p.element, "mouseleave"); + q && (q = q.destroy()); + va.prototype.destroy.call(p) + }}) + }}; + Ta = qa; + var ka; + if (!Da && !ga) { + ka = {init: function (a, b) { + var c = ["<", b, ' filled="f" stroked="f"'], + d = ["position: ", "absolute", ";"]; + (b === "shape" || b === ia) && d.push("left:0;top:0;width:1px;height:1px;"); + Ca && d.push("visibility: ", b === ia ? "hidden" : "visible"); + c.push(' style="', d.join(""), '"/>'); + if (b)c = b === ia || b === "span" || b === "img" ? c.join("") : a.prepVML(c), this.element = S(c); + this.renderer = a; + this.attrSetters = {} + }, add: function (a) { + var b = this.renderer, c = this.element, d = b.box, d = a ? a.element || a : d; + a && a.inverted && b.invertChild(c, d); + Ca && d.gVis === "hidden" && F(c, {visibility: "hidden"}); + d.appendChild(c); + this.added = !0; + this.alignOnAdd && !this.deferUpdateTransform && this.updateTransform(); + E(this, "add"); + return this + }, toggleChildren: function (a, b) { + for (var c = a.childNodes, d = c.length; d--;)F(c[d], {visibility: b}), c[d].nodeName === "DIV" && this.toggleChildren(c[d], b) + }, updateTransform: va.prototype.htmlUpdateTransform, attr: function (a, b) { + var c, d, e, f = this.element || {}, g = f.style, h = f.nodeName, i = this.renderer, j = this.symbolName, k, l = this.shadows, m, p = this.attrSetters, q = this; + ra(a) && s(b) && (c = a, a = {}, a[c] = b); + if (ra(a))c = a, q = c === "strokeWidth" || c === "stroke-width" ? + this.strokeweight : this[c]; else for (c in a)if (d = a[c], m = !1, e = p[c] && p[c](d, c), e !== !1 && d !== null) { + e !== A && (d = e); + if (j && /^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(c))k || (this.symbolAttr(a), k = !0), m = !0; else if (c === "d") { + d = d || []; + this.d = d.join(" "); + e = d.length; + for (m = []; e--;)m[e] = Ka(d[e]) ? t(d[e] * 10) - 5 : d[e] === "Z" ? "x" : d[e]; + d = m.join(" ") || "x"; + f.path = d; + if (l)for (e = l.length; e--;)l[e].path = l[e].cutOff ? this.cutOffPath(d, l[e].cutOff) : d; + m = !0 + } else if (c === "zIndex" || c === "visibility") { + if (Ca && c === "visibility" && + h === "DIV")f.gVis = d, this.toggleChildren(f, d), d === "visible" && (d = null); + d && (g[c] = d); + m = !0 + } else if (c === "width" || c === "height")d = x(0, d), this[c] = d, this.updateClipping ? (this[c] = d, this.updateClipping()) : g[c] = d, m = !0; else if (c === "x" || c === "y")this[c] = d, g[{x: "left", y: "top"}[c]] = d; else if (c === "class")f.className = d; else if (c === "stroke")d = i.color(d, f, c), c = "strokecolor"; else if (c === "stroke-width" || c === "strokeWidth")f.stroked = d ? !0 : !1, c = "strokeweight", this[c] = d, Ka(d) && (d += "px"); else if (c === "dashstyle")(f.getElementsByTagName("stroke")[0] || + S(i.prepVML([""]), null, null, f))[c] = d || "solid", this.dashstyle = d, m = !0; else if (c === "fill")h === "SPAN" ? g.color = d : (f.filled = d !== U ? !0 : !1, d = i.color(d, f, c), c = "fillcolor"); else if (h === "shape" && c === "rotation")this[c] = d; else if (c === "translateX" || c === "translateY" || c === "rotation")this[c] = d, this.updateTransform(), m = !0; else if (c === "text")this.bBox = null, f.innerHTML = d, m = !0; + if (l && c === "visibility")for (e = l.length; e--;)l[e].style[c] = d; + m || (Ca ? f[c] = d : z(f, c, d)) + } + return q + }, clip: function (a) { + var b = this, c = a.members, d = + b.element, e = d.parentNode; + c.push(b); + b.destroyClip = function () { + za(c, b) + }; + e && e.className === "highcharts-tracker" && !Ca && F(d, {visibility: "hidden"}); + return b.css(a.getCSS(b)) + }, css: va.prototype.htmlCss, safeRemoveChild: function (a) { + a.parentNode && Qa(a) + }, destroy: function () { + this.destroyClip && this.destroyClip(); + return va.prototype.destroy.apply(this) + }, empty: function () { + for (var a = this.element.childNodes, b = a.length, c; b--;)c = a[b], c.parentNode.removeChild(c) + }, on: function (a, b) { + this.element["on" + a] = function () { + var a = N.event; + a.target = a.srcElement; + b(a) + }; + return this + }, cutOffPath: function (a, b) { + var c, a = a.split(/[ ,]/); + c = a.length; + if (c === 9 || c === 11)a[c - 4] = a[c - 2] = w(a[c - 2]) - 10 * b; + return a.join(" ") + }, shadow: function (a, b, c) { + var d = [], e = this.element, f = this.renderer, g, h = e.style, i, j = e.path, k, l; + j && typeof j.value !== "string" && (j = "x"); + l = j; + if (a) { + for (a = 1; a <= 3; a++) { + k = 7 - 2 * a; + c && (l = this.cutOffPath(j.value, k + 0.5)); + i = ['']; + g = + S(f.prepVML(i), null, {left: w(h.left) + 1, top: w(h.top) + 1}); + if (c)g.cutOff = k + 1; + i = ['']; + S(f.prepVML(i), null, null, g); + b ? b.element.appendChild(g) : e.parentNode.insertBefore(g, e); + d.push(g) + } + this.shadows = d + } + return this + }}; + ka = ca(va, ka); + var ha = {Element: ka, isIE8: ya.indexOf("MSIE 8.0") > -1, init: function (a, b, c) { + var d, e; + this.alignedObjects = []; + d = this.createElement(ia); + e = d.element; + e.style.position = "relative"; + a.appendChild(d.element); + this.box = e; + this.boxWrapper = d; + this.setSize(b, c, + !1); + if (!B.namespaces.hcv)B.namespaces.add("hcv", "urn:schemas-microsoft-com:vml"), B.createStyleSheet().cssText = "hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } " + }, isHidden: function () { + return!this.box.offsetWidth + }, clipRect: function (a, b, c, d) { + var e = this.createElement(); + return u(e, {members: [], left: a, top: b, width: c, height: d, getCSS: function (a) { + var b = a.inverted, c = this.top, d = this.left, e = d + this.width, k = c + this.height, c = {clip: "rect(" + t(b ? d : c) + "px," + t(b ? k : + e) + "px," + t(b ? e : k) + "px," + t(b ? c : d) + "px)"}; + !b && Ca && a.element.nodeName !== "IMG" && u(c, {width: e + "px", height: k + "px"}); + return c + }, updateClipping: function () { + n(e.members, function (a) { + a.css(e.getCSS(a)) + }) + }}) + }, color: function (a, b, c) { + var d, e = /^rgba/, f, g = U; + a && a.linearGradient ? f = "gradient" : a && a.radialGradient && (f = "pattern"); + if (f) { + var h, i, j = a.linearGradient || a.radialGradient, k, l, m, p, q, o, r = "", a = a.stops, y, s = []; + l = a[0]; + y = a[a.length - 1]; + l[0] > 0 && a.unshift([0, l[1]]); + y[0] < 1 && a.push([1, y[1]]); + n(a, function (a, b) { + e.test(a[1]) ? (d = + pa(a[1]), h = d.get("rgb"), i = d.get("a")) : (h = a[1], i = 1); + s.push(a[0] * 100 + "% " + h); + b ? (p = i, q = h) : (m = i, o = h) + }); + f === "gradient" ? (k = j.x1 || j[0] || 0, a = j.y1 || j[1] || 0, l = j.x2 || j[2] || 0, j = j.y2 || j[3] || 0, k = 90 - L.atan((j - a) / (l - k)) * 180 / xa) : (g = j.r * 2, r = 'src="http://code.highcharts.com/gfx/radial-gradient.png" size="' + g + "," + g + '" origin="0.5,0.5" position="' + j.cx + "," + j.cy + '" color2="' + o + '" ', g = q); + c === "fill" ? (c = [''], + S(this.prepVML(c), null, null, b)) : g = h + } else if (e.test(a) && b.tagName !== "IMG")d = pa(a), c = ["<", c, ' opacity="', d.get("a"), '"/>'], S(this.prepVML(c), null, null, b), g = d.get("rgb"); else { + b = b.getElementsByTagName(c); + if (b.length)b[0].opacity = 1; + g = a + } + return g + }, prepVML: function (a) { + var b = this.isIE8, a = a.join(""); + b ? (a = a.replace("/>", ' xmlns="urn:schemas-microsoft-com:vml" />'), a = a.indexOf('style="') === -1 ? a.replace("/>", ' style="display:inline-block;behavior:url(#default#VML);" />') : a.replace('style="', 'style="display:inline-block;behavior:url(#default#VML);')) : + a = a.replace("<", " 1 && f.css({left: b, top: c, width: d, + height: e}); + return f + }, rect: function (a, b, c, d, e, f) { + if (aa(a))b = a.y, c = a.width, d = a.height, f = a.strokeWidth, a = a.x; + var g = this.symbol("rect"); + g.r = e; + return g.attr(g.crisp(f, a, b, x(c, 0), x(d, 0))) + }, invertChild: function (a, b) { + var c = b.style; + F(a, {flip: "x", left: w(c.width) - 1, top: w(c.height) - 1, rotation: -90}) + }, symbols: {arc: function (a, b, c, d, e) { + var f = e.start, g = e.end, h = e.r || c || d, c = X(f), d = da(f), i = X(g), j = da(g), k = e.innerR, l = 0.08 / h, m = k && 0.1 / k || 0; + if (g - f === 0)return["x"]; else 2 * xa - g + f < l ? i = -l : g - f < m && (i = X(f + m)); + f = ["wa", a - h, b - h, a + h, + b + h, a + h * c, b + h * d, a + h * i, b + h * j]; + e.open && f.push("M", a - k, b - k); + f.push("at", a - k, b - k, a + k, b + k, a + k * i, b + k * j, a + k * c, b + k * d, "x", "e"); + return f + }, circle: function (a, b, c, d) { + return["wa", a, b, a + c, b + d, a + c, b + d / 2, a + c, b + d / 2, "e"] + }, rect: function (a, b, c, d, e) { + var f = a + c, g = b + d, h; + !s(e) || !e.r ? f = qa.prototype.symbols.square.apply(0, arguments) : (h = O(e.r, c, d), f = ["M", a + h, b, "L", f - h, b, "wa", f - 2 * h, b, f, b + 2 * h, f - h, b, f, b + h, "L", f, g - h, "wa", f - 2 * h, g - 2 * h, f, g, f, g - h, f - h, g, "L", a + h, g, "wa", a, g - 2 * h, a + 2 * h, g, a + h, g, a, g - h, "L", a, b + h, "wa", a, b, a + 2 * h, b + 2 * h, a, b + h, a + + h, b, "x", "e"]); + return f + }}}; + ka = function () { + this.init.apply(this, arguments) + }; + ka.prototype = C(qa.prototype, ha); + Ta = ka + } + var fb, Nb; + if (ga)fb = function () { + }, fb.prototype.symbols = {}, Nb = function () { + function a() { + var a = b.length, d; + for (d = 0; d < a; d++)b[d](); + b = [] + } + + var b = []; + return{push: function (c, d) { + b.length === 0 && Ib(d, a); + b.push(c) + }} + }(); + Ta = ka || fb || qa; + Sa.prototype = {addLabel: function () { + var a = this.axis, b = a.options, c = a.chart, d = a.horiz, e = a.categories, f = this.pos, g = b.labels, h = a.tickPositions, d = e && d && e.length && !g.step && !g.staggerLines && !g.rotation && c.plotWidth / h.length || !d && c.plotWidth / 2, i = f === h[0], j = f === h[h.length - 1], k = e && s(e[f]) ? e[f] : f, e = this.label, h = h.info, l; + a.isDatetimeAxis && h && (l = b.dateTimeLabelFormats[h.higherRanks[f] || h.unitName]); + this.isFirst = i; + this.isLast = j; + b = a.labelFormatter.call({axis: a, chart: c, isFirst: i, isLast: j, dateTimeLabelFormat: l, value: a.isLog ? ja(ba(k)) : k}); + f = d && {width: x(1, t(d - 2 * (g.padding || 10))) + "px"}; + f = u(f, g.style); + if (s(e))e && e.attr({text: b}).css(f); else { + d = {align: g.align}; + if (Ka(g.rotation))d.rotation = g.rotation; + this.label = s(b) && g.enabled ? c.renderer.text(b, 0, 0, g.useHTML).attr(d).css(f).add(a.axisGroup) : null + } + }, getLabelSize: function () { + var a = this.label, b = this.axis; + return a ? (this.labelBBox = a.getBBox(!0))[b.horiz ? "height" : "width"] : 0 + }, getLabelSides: function () { + var a = this.axis.options.labels, b = this.labelBBox.width, a = b * {left: 0, center: 0.5, right: 1}[a.align] - a.x; + return[-a, b - a] + }, handleOverflow: function (a, b) { + var c = !0, d = this.axis, e = d.chart, f = this.isFirst, g = this.isLast, h = b.x, i = d.reversed, j = d.tickPositions; + if (f || g) { + var k = + this.getLabelSides(), l = k[0], k = k[1], e = e.plotLeft, m = e + d.len, j = (d = d.ticks[j[a + (f ? 1 : -1)]]) && d.label.xy.x + d.getLabelSides()[f ? 0 : 1]; + f && !i || g && i ? h + l < e && (h = e - l, d && h + k > j && (c = !1)) : h + k > m && (h = m - k, d && h + l < j && (c = !1)); + b.x = h + } + return c + }, getPosition: function (a, b, c, d) { + var e = this.axis, f = e.chart, g = d && f.oldChartHeight || f.chartHeight; + return{x: a ? e.translate(b + c, null, null, d) + e.transB : e.left + e.offset + (e.opposite ? (d && f.oldChartWidth || f.chartWidth) - e.right - e.left : 0), y: a ? g - e.bottom + e.offset - (e.opposite ? e.height : 0) : g - e.translate(b + + c, null, null, d) - e.transB} + }, getLabelPosition: function (a, b, c, d, e, f, g, h) { + var i = this.axis, j = i.transA, k = i.reversed, i = i.staggerLines, a = a + e.x - (f && d ? f * j * (k ? -1 : 1) : 0), b = b + e.y - (f && !d ? f * j * (k ? 1 : -1) : 0); + s(e.y) || (b += w(c.styles.lineHeight) * 0.9 - c.getBBox().height / 2); + i && (b += g / (h || 1) % i * 16); + return{x: a, y: b} + }, getMarkPath: function (a, b, c, d, e, f) { + return f.crispLine(["M", a, b, "L", a + (e ? 0 : -c), b + (e ? c : 0)], d) + }, render: function (a, b) { + var c = this.axis, d = c.options, e = c.chart.renderer, f = c.horiz, g = this.type, h = this.label, i = this.pos, j = d.labels, + k = this.gridLine, l = g ? g + "Grid" : "grid", m = g ? g + "Tick" : "tick", p = d[l + "LineWidth"], q = d[l + "LineColor"], n = d[l + "LineDashStyle"], r = d[m + "Length"], l = d[m + "Width"] || 0, y = d[m + "Color"], s = d[m + "Position"], m = this.mark, t = j.step, v = !0, H = d.categories && d.tickmarkPlacement === "between" ? 0.5 : 0, J = this.getPosition(f, i, H, b), K = J.x, J = J.y, x = c.staggerLines; + if (p) { + i = c.getPlotLinePath(i + H, p, b); + if (k === A) { + k = {stroke: q, "stroke-width": p}; + if (n)k.dashstyle = n; + if (!g)k.zIndex = 1; + this.gridLine = k = p ? e.path(i).attr(k).add(c.gridGroup) : null + } + if (!b && k && i)k[this.isNew ? + "attr" : "animate"]({d: i}) + } + if (l)s === "inside" && (r = -r), c.opposite && (r = -r), g = this.getMarkPath(K, J, r, l, f, e), m ? m.animate({d: g}) : this.mark = e.path(g).attr({stroke: y, "stroke-width": l}).add(c.axisGroup); + if (h && !isNaN(K))h.xy = J = this.getLabelPosition(K, J, h, f, j, H, a, t), this.isFirst && !o(d.showFirstLabel, 1) || this.isLast && !o(d.showLastLabel, 1) ? v = !1 : !x && f && j.overflow === "justify" && !this.handleOverflow(a, J) && (v = !1), t && a % t && (v = !1), v ? (h[this.isNew ? "attr" : "animate"](J), h.show(), this.isNew = !1) : h.hide() + }, destroy: function () { + Ba(this, + this.axis) + }}; + nb.prototype = {render: function () { + var a = this, b = a.axis, c = b.horiz, d = (b.pointRange || 0) / 2, e = a.options, f = e.label, g = a.label, h = e.width, i = e.to, j = e.from, k = s(j) && s(i), l = e.value, m = e.dashStyle, p = a.svgElem, q = [], n, r = e.color, y = e.zIndex, t = e.events, u = b.chart.renderer; + b.isLog && (j = ma(j), i = ma(i), l = ma(l)); + if (h) { + if (q = b.getPlotLinePath(l, h), d = {stroke: r, "stroke-width": h}, m)d.dashstyle = m + } else if (k) { + if (j = x(j, b.min - d), i = O(i, b.max + d), q = b.getPlotBandPath(j, i, e), d = {fill: r}, e.borderWidth)d.stroke = e.borderColor, d["stroke-width"] = + e.borderWidth + } else return; + if (s(y))d.zIndex = y; + if (p)q ? p.animate({d: q}, null, p.onGetPath) : (p.hide(), p.onGetPath = function () { + p.show() + }); else if (q && q.length && (a.svgElem = p = u.path(q).attr(d).add(), t))for (n in e = function (b) { + p.on(b, function (c) { + t[b].apply(a, [c]) + }) + }, t)e(n); + if (f && s(f.text) && q && q.length && b.width > 0 && b.height > 0) { + f = C({align: c && k && "center", x: c ? !k && 4 : 10, verticalAlign: !c && k && "middle", y: c ? k ? 16 : 10 : k ? 6 : -4, rotation: c && !k && 90}, f); + if (!g)a.label = g = u.text(f.text, 0, 0).attr({align: f.textAlign || f.align, rotation: f.rotation, + zIndex: y}).css(f.style).add(); + b = [q[1], q[4], o(q[6], q[1])]; + q = [q[2], q[5], o(q[7], q[2])]; + c = Pa(b); + k = Pa(q); + g.align(f, !1, {x: c, y: k, width: Aa(b) - c, height: Aa(q) - k}); + g.show() + } else g && g.hide(); + return a + }, destroy: function () { + za(this.axis.plotLinesAndBands, this); + Ba(this, this.axis) + }}; + Cb.prototype = {destroy: function () { + Ba(this, this.axis) + }, setTotal: function (a) { + this.cum = this.total = a + }, render: function (a) { + var b = this.options.formatter.call(this); + this.label ? this.label.attr({text: b, visibility: "hidden"}) : this.label = this.axis.chart.renderer.text(b, + 0, 0).css(this.options.style).attr({align: this.textAlign, rotation: this.options.rotation, visibility: "hidden"}).add(a) + }, setOffset: function (a, b) { + var c = this.axis, d = c.chart, e = d.inverted, f = this.isNegative, g = c.translate(this.total, 0, 0, 0, 1), c = c.translate(0), c = M(g - c), h = d.xAxis[0].translate(this.x) + a, d = d.plotHeight, e = {x: e ? f ? g : g - c : h, y: e ? d - h - b : f ? d - g - c : d - g, width: e ? c : b, height: e ? b : c}; + this.label && this.label.align(this.alignOptions, null, e).attr({visibility: "visible"}) + }}; + ob.prototype = {defaultOptions: {dateTimeLabelFormats: {millisecond: "%H:%M:%S.%L", + second: "%H:%M:%S", minute: "%H:%M", hour: "%H:%M", day: "%e. %b", week: "%e. %b", month: "%b '%y", year: "%Y"}, endOnTick: !1, gridLineColor: "#C0C0C0", labels: G, lineColor: "#C0D0E0", lineWidth: 1, minPadding: 0.01, maxPadding: 0.01, minorGridLineColor: "#E0E0E0", minorGridLineWidth: 1, minorTickColor: "#A0A0A0", minorTickLength: 2, minorTickPosition: "outside", startOfWeek: 1, startOnTick: !1, tickColor: "#C0D0E0", tickLength: 5, tickmarkPlacement: "between", tickPixelInterval: 100, tickPosition: "outside", tickWidth: 1, title: {align: "middle", style: {color: "#6D869F", + fontWeight: "bold"}}, type: "linear"}, defaultYAxisOptions: {endOnTick: !0, gridLineWidth: 1, tickPixelInterval: 72, showLastLabel: !0, labels: {align: "right", x: -8, y: 3}, lineWidth: 0, maxPadding: 0.05, minPadding: 0.05, startOnTick: !0, tickWidth: 0, title: {rotation: 270, text: "Y-values"}, stackLabels: {enabled: !1, formatter: function () { + return this.total + }, style: G.style}}, defaultLeftAxisOptions: {labels: {align: "right", x: -8, y: null}, title: {rotation: 270}}, defaultRightAxisOptions: {labels: {align: "left", x: 8, y: null}, title: {rotation: 90}}, + defaultBottomAxisOptions: {labels: {align: "center", x: 0, y: 14}, title: {rotation: 0}}, defaultTopAxisOptions: {labels: {align: "center", x: 0, y: -5}, title: {rotation: 0}}, init: function (a, b) { + var c = b.isX; + this.horiz = a.inverted ? !c : c; + this.xOrY = (this.isXAxis = c) ? "x" : "y"; + this.opposite = b.opposite; + this.side = this.horiz ? this.opposite ? 0 : 2 : this.opposite ? 1 : 3; + this.setOptions(b); + var d = this.options, e = d.type, f = e === "datetime"; + this.labelFormatter = d.labels.formatter || this.defaultLabelFormatter; + this.staggerLines = this.horiz && d.labels.staggerLines; + this.userOptions = b; + this.minPixelPadding = 0; + this.chart = a; + this.reversed = d.reversed; + this.categories = d.categories; + this.isLog = e === "logarithmic"; + this.isLinked = s(d.linkedTo); + this.isDatetimeAxis = f; + this.ticks = {}; + this.minorTicks = {}; + this.plotLinesAndBands = []; + this.alternateBands = {}; + this.len = 0; + this.minRange = this.userMinRange = d.minRange || d.maxZoom; + this.range = d.range; + this.offset = d.offset || 0; + this.stacks = {}; + this.min = this.max = null; + var g, d = this.options.events; + a.axes.push(this); + a[c ? "xAxis" : "yAxis"].push(this); + this.series = + []; + if (a.inverted && c && this.reversed === A)this.reversed = !0; + this.removePlotLine = this.removePlotBand = this.removePlotBandOrLine; + this.addPlotLine = this.addPlotBand = this.addPlotBandOrLine; + for (g in d)I(this, g, d[g]); + if (this.isLog)this.val2lin = ma, this.lin2val = ba + }, setOptions: function (a) { + this.options = C(this.defaultOptions, this.isXAxis ? {} : this.defaultYAxisOptions, [this.defaultTopAxisOptions, this.defaultRightAxisOptions, this.defaultBottomAxisOptions, this.defaultLeftAxisOptions][this.side], a) + }, defaultLabelFormatter: function () { + var a = + this.axis, b = this.value, c = a.tickInterval, d = this.dateTimeLabelFormat; + return a.categories ? b : d ? db(d, b) : c % 1E6 === 0 ? b / 1E6 + "M" : c % 1E3 === 0 ? b / 1E3 + "k" : b >= 1E3 ? Xa(b, 0) : Xa(b, -1) + }, getSeriesExtremes: function () { + var a = this, b = a.chart, c = a.stacks, d = [], e = [], f; + a.dataMin = a.dataMax = null; + n(a.series, function (g) { + if (g.visible || !b.options.chart.ignoreHiddenSeries) { + var h = g.options, i, j, k, l, m, p, q, n, r, y = h.threshold, t, u = [], v = 0; + if (a.isLog && y <= 0)y = h.threshold = null; + if (a.isXAxis) { + if (h = g.xData, h.length)a.dataMin = O(o(a.dataMin, h[0]), Pa(h)), + a.dataMax = x(o(a.dataMax, h[0]), Aa(h)) + } else { + var H, J, K, C = g.cropped, Ha = g.xAxis.getExtremes(), w = !!g.modifyValue; + i = h.stacking; + a.usePercentage = i === "percent"; + if (i)m = h.stack, l = g.type + o(m, ""), p = "-" + l, g.stackKey = l, j = d[l] || [], d[l] = j, k = e[p] || [], e[p] = k; + if (a.usePercentage)a.dataMin = 0, a.dataMax = 99; + h = g.processedXData; + q = g.processedYData; + t = q.length; + for (f = 0; f < t; f++)if (n = h[f], r = q[f], r !== null && r !== A && (i ? (J = (H = r < y) ? k : j, K = H ? p : l, r = J[n] = s(J[n]) ? J[n] + r : r, c[K] || (c[K] = {}), c[K][n] || (c[K][n] = new Cb(a, a.options.stackLabels, H, n, + m)), c[K][n].setTotal(r)) : w && (r = g.modifyValue(r)), C || (h[f + 1] || n) >= Ha.min && (h[f - 1] || n) <= Ha.max))if (n = r.length)for (; n--;)r[n] !== null && (u[v++] = r[n]); else u[v++] = r; + if (!a.usePercentage && u.length)a.dataMin = O(o(a.dataMin, u[0]), Pa(u)), a.dataMax = x(o(a.dataMax, u[0]), Aa(u)); + if (s(y))if (a.dataMin >= y)a.dataMin = y, a.ignoreMinPadding = !0; else if (a.dataMax < y)a.dataMax = y, a.ignoreMaxPadding = !0 + } + } + }) + }, translate: function (a, b, c, d, e) { + var f = this.len, g = 1, h = 0, i = d ? this.oldTransA : this.transA, d = d ? this.oldMin : this.min, e = this.options.ordinal || + this.isLog && e; + if (!i)i = this.transA; + c && (g *= -1, h = f); + this.reversed && (g *= -1, h -= g * f); + b ? (this.reversed && (a = f - a), a = a / i + d, e && (a = this.lin2val(a))) : (e && (a = this.val2lin(a)), a = g * (a - d) * i + h + g * this.minPixelPadding); + return a + }, getPlotLinePath: function (a, b, c) { + var d = this.chart, e = this.left, f = this.top, g, h, i, a = this.translate(a, null, null, c), j = c && d.oldChartHeight || d.chartHeight, k = c && d.oldChartWidth || d.chartWidth, l; + g = this.transB; + c = h = t(a + g); + g = i = t(j - a - g); + if (isNaN(a))l = !0; else if (this.horiz) { + if (g = f, i = j - this.bottom, c < e || c > e + this.width)l = !0 + } else if (c = e, h = k - this.right, g < f || g > f + this.height)l = !0; + return l ? null : d.renderer.crispLine(["M", c, g, "L", h, i], b || 0) + }, getPlotBandPath: function (a, b) { + var c = this.getPlotLinePath(b), d = this.getPlotLinePath(a); + d && c ? d.push(c[4], c[5], c[1], c[2]) : d = null; + return d + }, getLinearTickPositions: function (a, b, c) { + for (var d, b = ja(W(b / a) * a), c = ja(wa(c / a) * a), e = []; b <= c;) { + e.push(b); + b = ja(b + a); + if (b === d)break; + d = b + } + return e + }, getLogTickPositions: function (a, b, c, d) { + var e = this.options, f = this.len, g = []; + if (!d)this._minorAutoInterval = null; + if (a >= 0.5)a = t(a), g = this.getLinearTickPositions(a, b, c); else if (a >= 0.08)for (var f = W(b), h, i, j, k, l, e = a > 0.3 ? [1, 2, 4] : a > 0.15 ? [1, 2, 4, 6, 8] : [1, 2, 3, 4, 5, 6, 7, 8, 9]; f < c + 1 && !l; f++) { + i = e.length; + for (h = 0; h < i && !l; h++)j = ma(ba(f) * e[h]), j > b && g.push(k), k > c && (l = !0), k = j + } else if (b = ba(b), c = ba(c), a = e[d ? "minorTickInterval" : "tickInterval"], a = o(a === "auto" ? null : a, this._minorAutoInterval, (c - b) * (e.tickPixelInterval / (d ? 5 : 1)) / ((d ? f / this.tickPositions.length : f) || 1)), a = gb(a, null, L.pow(10, W(L.log(a) / L.LN10))), g = Ea(this.getLinearTickPositions(a, + b, c), ma), !d)this._minorAutoInterval = a / 5; + if (!d)this.tickInterval = a; + return g + }, getMinorTickPositions: function () { + var a = this.tickPositions, b = this.minorTickInterval, c = [], d, e; + if (this.isLog) { + e = a.length; + for (d = 1; d < e; d++)c = c.concat(this.getLogTickPositions(b, a[d - 1], a[d], !0)) + } else for (a = this.min + (a[0] - this.min) % b; a <= this.max; a += b)c.push(a); + return c + }, adjustForMinRange: function () { + var a = this.options, b = this.min, c = this.max, d, e = this.dataMax - this.dataMin >= this.minRange, f, g, h, i, j; + if (this.isXAxis && this.minRange === A && !this.isLog)s(a.min) || s(a.max) ? this.minRange = null : (n(this.series, function (a) { + i = a.xData; + for (g = j = a.xIncrement ? 1 : i.length - 1; g > 0; g--)if (h = i[g] - i[g - 1], f === A || h < f)f = h + }), this.minRange = O(f * 5, this.dataMax - this.dataMin)); + if (c - b < this.minRange) { + var k = this.minRange; + d = (k - c + b) / 2; + d = [b - d, o(a.min, b - d)]; + if (e)d[2] = this.dataMin; + b = Aa(d); + c = [b + k, o(a.max, b + k)]; + if (e)c[2] = this.dataMax; + c = Pa(c); + c - b < k && (d[0] = c - k, d[1] = o(a.min, c - k), b = Aa(d)) + } + this.min = b; + this.max = c + }, setAxisTranslation: function () { + var a = this.max - this.min, b = 0, c, d, e = this.transA; + if (this.isXAxis)this.isLinked ? b = this.linkedParent.pointRange : n(this.series, function (a) { + b = x(b, a.pointRange); + d = a.closestPointRange; + !a.noSharedTooltip && s(d) && (c = s(c) ? O(c, d) : d) + }), this.pointRange = b, this.closestPointRange = c; + this.oldTransA = e; + this.translationSlope = this.transA = e = this.len / (a + b || 1); + this.transB = this.horiz ? this.left : this.bottom; + this.minPixelPadding = e * (b / 2) + }, setTickPositions: function (a) { + var b = this, c = b.chart, d = b.options, e = b.isLog, f = b.isDatetimeAxis, g = b.isXAxis, h = b.isLinked, i = b.options.tickPositioner, + j = d.maxPadding, k = d.minPadding, l = d.tickInterval, m = d.tickPixelInterval, p = b.categories; + h ? (b.linkedParent = c[g ? "xAxis" : "yAxis"][d.linkedTo], c = b.linkedParent.getExtremes(), b.min = o(c.min, c.dataMin), b.max = o(c.max, c.dataMax), d.type !== b.linkedParent.options.type && mb(11, 1)) : (b.min = o(b.userMin, d.min, b.dataMin), b.max = o(b.userMax, d.max, b.dataMax)); + if (e)!a && O(b.min, o(b.dataMin, b.min)) <= 0 && mb(10, 1), b.min = ja(ma(b.min)), b.max = ja(ma(b.max)); + if (b.range && (b.userMin = b.min = x(b.min, b.max - b.range), b.userMax = b.max, a))b.range = + null; + b.adjustForMinRange(); + if (!p && !b.usePercentage && !h && s(b.min) && s(b.max)) { + c = b.max - b.min || 1; + if (!s(d.min) && !s(b.userMin) && k && (b.dataMin < 0 || !b.ignoreMinPadding))b.min -= c * k; + if (!s(d.max) && !s(b.userMax) && j && (b.dataMax > 0 || !b.ignoreMaxPadding))b.max += c * j + } + b.tickInterval = b.min === b.max || b.min === void 0 || b.max === void 0 ? 1 : h && !l && m === b.linkedParent.options.tickPixelInterval ? b.linkedParent.tickInterval : o(l, p ? 1 : (b.max - b.min) * m / (b.len || 1)); + g && !a && n(b.series, function (a) { + a.processData(b.min !== b.oldMin || b.max !== b.oldMax) + }); + b.setAxisTranslation(); + b.beforeSetTickPositions && b.beforeSetTickPositions(); + if (b.postProcessTickInterval)b.tickInterval = b.postProcessTickInterval(b.tickInterval); + if (!f && !e && (a = L.pow(10, W(L.log(b.tickInterval) / L.LN10)), !s(d.tickInterval)))b.tickInterval = gb(b.tickInterval, null, a, d); + b.minorTickInterval = d.minorTickInterval === "auto" && b.tickInterval ? b.tickInterval / 5 : d.minorTickInterval; + b.tickPositions = i = d.tickPositions || i && i.apply(b, [b.min, b.max]); + if (!i)i = f ? (b.getNonLinearTimeTicks || Pb)(Ob(b.tickInterval, + d.units), b.min, b.max, d.startOfWeek, b.ordinalPositions, b.closestPointRange, !0) : e ? b.getLogTickPositions(b.tickInterval, b.min, b.max) : b.getLinearTickPositions(b.tickInterval, b.min, b.max), b.tickPositions = i; + if (!h)e = i[0], f = i[i.length - 1], d.startOnTick ? b.min = e : b.min > e && i.shift(), d.endOnTick ? b.max = f : b.max < f && i.pop() + }, setMaxTicks: function () { + var a = this.chart, b = a.maxTicks, c = this.tickPositions, d = this.xOrY; + b || (b = {x: 0, y: 0}); + if (!this.isLinked && !this.isDatetimeAxis && c.length > b[d] && this.options.alignTicks !== !1)b[d] = + c.length; + a.maxTicks = b + }, adjustTickAmount: function () { + var a = this.xOrY, b = this.tickPositions, c = this.chart.maxTicks; + if (c && c[a] && !this.isDatetimeAxis && !this.categories && !this.isLinked && this.options.alignTicks !== !1) { + var d = this.tickAmount, e = b.length; + this.tickAmount = a = c[a]; + if (e < a) { + for (; b.length < a;)b.push(ja(b[b.length - 1] + this.tickInterval)); + this.transA *= (e - 1) / (a - 1); + this.max = b[b.length - 1] + } + if (s(d) && a !== d)this.isDirty = !0 + } + }, setScale: function () { + var a = this.stacks, b, c, d, e; + this.oldMin = this.min; + this.oldMax = this.max; + this.oldAxisLength = this.len; + this.setAxisSize(); + e = this.len !== this.oldAxisLength; + n(this.series, function (a) { + if (a.isDirtyData || a.isDirty || a.xAxis.isDirty)d = !0 + }); + if (e || d || this.isLinked || this.userMin !== this.oldUserMin || this.userMax !== this.oldUserMax)if (this.getSeriesExtremes(), this.setTickPositions(), this.oldUserMin = this.userMin, this.oldUserMax = this.userMax, !this.isDirty)this.isDirty = e || this.min !== this.oldMin || this.max !== this.oldMax; + if (!this.isXAxis)for (b in a)for (c in a[b])a[b][c].cum = a[b][c].total; + this.setMaxTicks() + }, + setExtremes: function (a, b, c, d, e) { + var f = this, g = f.chart, c = o(c, !0), e = u(e, {min: a, max: b}); + E(f, "setExtremes", e, function () { + f.userMin = a; + f.userMax = b; + f.isDirtyExtremes = !0; + c && g.redraw(d) + }) + }, setAxisSize: function () { + var a = this.chart, b = this.options, c = b.offsetLeft || 0, d = b.offsetRight || 0; + this.left = o(b.left, a.plotLeft + c); + this.top = o(b.top, a.plotTop); + this.width = o(b.width, a.plotWidth - c + d); + this.height = o(b.height, a.plotHeight); + this.bottom = a.chartHeight - this.height - this.top; + this.right = a.chartWidth - this.width - this.left; + this.len = + x(this.horiz ? this.width : this.height, 0) + }, getExtremes: function () { + var a = this.isLog; + return{min: a ? ja(ba(this.min)) : this.min, max: a ? ja(ba(this.max)) : this.max, dataMin: this.dataMin, dataMax: this.dataMax, userMin: this.userMin, userMax: this.userMax} + }, getThreshold: function (a) { + var b = this.isLog, c = b ? ba(this.min) : this.min, b = b ? ba(this.max) : this.max; + c > a || a === null ? a = c : b < a && (a = b); + return this.translate(a, 0, 1, 0, 1) + }, addPlotBandOrLine: function (a) { + a = (new nb(this, a)).render(); + this.plotLinesAndBands.push(a); + return a + }, getOffset: function () { + var a = + this, b = a.chart, c = b.renderer, d = a.options, e = a.tickPositions, f = a.ticks, g = a.horiz, h = a.side, i, j = 0, k, l = 0, m = d.title, p = d.labels, q = 0, fa = b.axisOffset, r = [-1, 1, 1, -1][h], y; + a.hasData = b = a.series.length && s(a.min) && s(a.max); + a.showAxis = i = b || o(d.showEmpty, !0); + if (!a.axisGroup)a.axisGroup = c.g("axis").attr({zIndex: d.zIndex || 7}).add(), a.gridGroup = c.g("grid").attr({zIndex: d.gridZIndex || 1}).add(); + if (b || a.isLinked)n(e, function (b) { + f[b] ? f[b].addLabel() : f[b] = new Sa(a, b) + }), n(e, function (a) { + if (h === 0 || h === 2 || {1: "left", 3: "right"}[h] === + p.align)q = x(f[a].getLabelSize(), q) + }), a.staggerLines && (q += (a.staggerLines - 1) * 16); else for (y in f)f[y].destroy(), delete f[y]; + if (m && m.text) { + if (!a.axisTitle)a.axisTitle = c.text(m.text, 0, 0, m.useHTML).attr({zIndex: 7, rotation: m.rotation || 0, align: m.textAlign || {low: "left", middle: "center", high: "right"}[m.align]}).css(m.style).add(a.axisGroup), a.axisTitle.isNew = !0; + if (i)j = a.axisTitle.getBBox()[g ? "height" : "width"], l = o(m.margin, g ? 5 : 10), k = m.offset; + a.axisTitle[i ? "show" : "hide"]() + } + a.offset = r * o(d.offset, fa[h]); + a.axisTitleMargin = + o(k, q + l + (h !== 2 && q && r * d.labels[g ? "y" : "x"])); + fa[h] = x(fa[h], a.axisTitleMargin + j + r * a.offset) + }, getLinePath: function (a) { + var b = this.chart, c = this.opposite, d = this.offset, e = this.horiz, f = this.left + (c ? this.width : 0) + d, c = b.chartHeight - this.bottom - (c ? this.height : 0) + d; + return b.renderer.crispLine(["M", e ? this.left : f, e ? c : this.top, "L", e ? b.chartWidth - this.right : f, e ? c : b.chartHeight - this.bottom], a) + }, getTitlePosition: function () { + var a = this.horiz, b = this.left, c = this.top, d = this.len, e = this.options.title, f = a ? b : c, g = this.opposite, + h = this.offset, i = w(e.style.fontSize || 12), d = {low: f + (a ? 0 : d), middle: f + d / 2, high: f + (a ? d : 0)}[e.align], b = (a ? c + this.height : b) + (a ? 1 : -1) * (g ? -1 : 1) * this.axisTitleMargin + (this.side === 2 ? i : 0); + return{x: a ? d : b + (g ? this.width : 0) + h + (e.x || 0), y: a ? b - (g ? this.height : 0) + h : d + (e.y || 0)} + }, render: function () { + var a = this, b = a.chart, c = b.renderer, d = a.options, e = a.isLog, f = a.isLinked, g = a.tickPositions, h = a.axisTitle, i = a.stacks, j = a.ticks, k = a.minorTicks, l = a.alternateBands, m = d.stackLabels, p = d.alternateGridColor, q = d.lineWidth, o, r = b.hasRendered && + s(a.oldMin) && !isNaN(a.oldMin), y = a.showAxis, t, u; + if (a.hasData || f)if (a.minorTickInterval && !a.categories && n(a.getMinorTickPositions(), function (b) { + k[b] || (k[b] = new Sa(a, b, "minor")); + r && k[b].isNew && k[b].render(null, !0); + k[b].isActive = !0; + k[b].render() + }), n(g.slice(1).concat([g[0]]), function (b, c) { + c = c === g.length - 1 ? 0 : c + 1; + if (!f || b >= a.min && b <= a.max)j[b] || (j[b] = new Sa(a, b)), r && j[b].isNew && j[b].render(c, !0), j[b].isActive = !0, j[b].render(c) + }), p && n(g, function (b, c) { + if (c % 2 === 0 && b < a.max)l[b] || (l[b] = new nb(a)), t = b, u = g[c + + 1] !== A ? g[c + 1] : a.max, l[b].options = {from: e ? ba(t) : t, to: e ? ba(u) : u, color: p}, l[b].render(), l[b].isActive = !0 + }), !a._addedPlotLB)n((d.plotLines || []).concat(d.plotBands || []), function (b) { + a.addPlotBandOrLine(b) + }), a._addedPlotLB = !0; + n([j, k, l], function (a) { + for (var b in a)a[b].isActive ? a[b].isActive = !1 : (a[b].destroy(), delete a[b]) + }); + if (q)o = a.getLinePath(q), a.axisLine ? a.axisLine.animate({d: o}) : a.axisLine = c.path(o).attr({stroke: d.lineColor, "stroke-width": q, zIndex: 7}).add(), a.axisLine[y ? "show" : "hide"](); + if (h && y)h[h.isNew ? + "attr" : "animate"](a.getTitlePosition()), h.isNew = !1; + if (m && m.enabled) { + var v, H, d = a.stackTotalGroup; + if (!d)a.stackTotalGroup = d = c.g("stack-labels").attr({visibility: "visible", zIndex: 6}).add(); + d.translate(b.plotLeft, b.plotTop); + for (v in i)for (H in b = i[v], b)b[H].render(d) + } + a.isDirty = !1 + }, removePlotBandOrLine: function (a) { + for (var b = this.plotLinesAndBands, c = b.length; c--;)b[c].id === a && b[c].destroy() + }, setTitle: function (a, b) { + var c = this.chart, d = this.options; + d.title = C(d.title, a); + this.axisTitle = void 0; + this.isDirty = !0; + o(b, !0) && c.redraw() + }, redraw: function () { + var a = this.chart; + a.tracker.resetTracker && a.tracker.resetTracker(!0); + this.render(); + n(this.plotLinesAndBands, function (a) { + a.render() + }); + n(this.series, function (a) { + a.isDirty = !0 + }) + }, setCategories: function (a, b) { + var c = this.chart; + this.categories = this.userOptions.categories = a; + n(this.series, function (a) { + a.translate(); + a.setTooltipPoints(!0) + }); + this.isDirty = !0; + o(b, !0) && c.redraw() + }, destroy: function () { + var a = this, b = a.stacks, c; + P(a); + for (c in b)Ba(b[c]), b[c] = null; + n([a.ticks, a.minorTicks, + a.alternateBands, a.plotLinesAndBands], function (a) { + Ba(a) + }); + n(["stackTotalGroup", "axisLine", "axisGroup", "gridGroup", "axisTitle"], function (b) { + a[b] && (a[b] = a[b].destroy()) + }) + }}; + pb.prototype = {destroy: function () { + n(this.crosshairs, function (a) { + a && a.destroy() + }); + if (this.label)this.label = this.label.destroy() + }, move: function (a, b) { + var c = this; + c.currentX = c.tooltipIsHidden ? a : (2 * c.currentX + a) / 3; + c.currentY = c.tooltipIsHidden ? b : (c.currentY + b) / 2; + c.label.attr({x: c.currentX, y: c.currentY}); + c.tooltipTick = M(a - c.currentX) > 1 || + M(b - c.currentY) > 1 ? function () { + c.move(a, b) + } : null + }, hide: function () { + if (!this.tooltipIsHidden) { + var a = this.chart.hoverPoints; + this.label.hide(); + a && n(a, function (a) { + a.setState() + }); + this.chart.hoverPoints = null; + this.tooltipIsHidden = !0 + } + }, hideCrosshairs: function () { + n(this.crosshairs, function (a) { + a && a.hide() + }) + }, getAnchor: function (a, b) { + var c, d = this.chart, e = d.inverted, f = 0, g = 0, a = na(a); + c = a[0].tooltipPos; + c || (n(a, function (a) { + f += a.plotX; + g += a.plotLow ? (a.plotLow + a.plotHigh) / 2 : a.plotY + }), f /= a.length, g /= a.length, c = [e ? d.plotWidth - + g : f, this.shared && !e && a.length > 1 && b ? b.chartY - d.plotTop : e ? d.plotHeight - f : g]); + return Ea(c, t) + }, getPosition: function (a, b, c) { + var d = this.chart, e = d.plotLeft, f = d.plotTop, g = d.plotWidth, h = d.plotHeight, i = o(this.options.distance, 12), j = c.plotX, c = c.plotY, d = j + e + (d.inverted ? i : -a - i), k = c - b + f + 15, l; + d < 7 && (d = e + j + i); + d + a > e + g && (d -= d + a - (e + g), k = c - b + f - i, l = !0); + k < f + 5 && (k = f + 5, l && c >= k && c <= k + b && (k = c + f + i)); + k + b > f + h && (k = x(f, f + h - b - i)); + return{x: d, y: k} + }, refresh: function (a, b) { + function c() { + var a = this.points || na(this), b = a[0].series, c; + c = [b.tooltipHeaderFormatter(a[0].key)]; + n(a, function (a) { + b = a.series; + c.push(b.tooltipFormatter && b.tooltipFormatter(a) || a.point.tooltipFormatter(b.tooltipOptions.pointFormat)) + }); + c.push(f.footerFormat || ""); + return c.join("") + } + + var d = this.chart, e = this.label, f = this.options, g, h, i, j = {}, k, l = []; + k = f.formatter || c; + var j = d.hoverPoints, m, p = f.crosshairs; + i = this.shared; + h = this.getAnchor(a, b); + g = h[0]; + h = h[1]; + i && (!a.series || !a.series.noSharedTooltip) ? (j && n(j, function (a) { + a.setState() + }), d.hoverPoints = a, n(a, function (a) { + a.setState("hover"); + l.push(a.getLabelConfig()) + }), + j = {x: a[0].category, y: a[0].y}, j.points = l, a = a[0]) : j = a.getLabelConfig(); + k = k.call(j); + j = a.series; + i = i || !j.isCartesian || j.tooltipOutsidePlot || d.isInsidePlot(g, h); + k === !1 || !i ? this.hide() : (this.tooltipIsHidden && e.show(), e.attr({text: k}), m = f.borderColor || a.color || j.color || "#606060", e.attr({stroke: m}), e = (f.positioner || this.getPosition).call(this, e.width, e.height, {plotX: g, plotY: h}), this.move(t(e.x), t(e.y)), this.tooltipIsHidden = !1); + if (p) { + p = na(p); + for (e = p.length; e--;)if (i = a.series[e ? "yAxis" : "xAxis"], p[e] && i)if (i = + i.getPlotLinePath(e ? o(a.stackY, a.y) : a.x, 1), this.crosshairs[e])this.crosshairs[e].attr({d: i, visibility: "visible"}); else { + j = {"stroke-width": p[e].width || 1, stroke: p[e].color || "#C0C0C0", zIndex: p[e].zIndex || 2}; + if (p[e].dashStyle)j.dashstyle = p[e].dashStyle; + this.crosshairs[e] = d.renderer.path(i).attr(j).add() + } + } + E(d, "tooltipRefresh", {text: k, x: g + d.plotLeft, y: h + d.plotTop, borderColor: m}) + }, tick: function () { + this.tooltipTick && this.tooltipTick() + }}; + Db.prototype = {normalizeMouseEvent: function (a) { + var b, c, d, a = a || N.event; + if (!a.target)a.target = + a.srcElement; + if (a.originalEvent)a = a.originalEvent; + if (a.event)a = a.event; + d = a.touches ? a.touches.item(0) : a; + this.chartPosition = b = Jb(this.chart.container); + d.pageX === A ? (c = a.x, b = a.y) : (c = d.pageX - b.left, b = d.pageY - b.top); + return u(a, {chartX: t(c), chartY: t(b)}) + }, getMouseCoordinates: function (a) { + var b = {xAxis: [], yAxis: []}, c = this.chart; + n(c.axes, function (d) { + var e = d.isXAxis; + b[e ? "xAxis" : "yAxis"].push({axis: d, value: d.translate((c.inverted ? !e : e) ? a.chartX - c.plotLeft : c.plotHeight - a.chartY + c.plotTop, !0)}) + }); + return b + }, onmousemove: function (a) { + var b = + this.chart, c = b.series, d, e, f = b.hoverPoint, g = b.hoverSeries, h, i, j = b.chartWidth, k = b.inverted ? b.plotHeight + b.plotTop - a.chartY : a.chartX - b.plotLeft; + if (b.tooltip && this.options.tooltip.shared && (!g || !g.noSharedTooltip)) { + e = []; + h = c.length; + for (i = 0; i < h; i++)if (c[i].visible && c[i].options.enableMouseTracking !== !1 && !c[i].noSharedTooltip && c[i].tooltipPoints.length)d = c[i].tooltipPoints[k], d._dist = M(k - d.plotX), j = O(j, d._dist), e.push(d); + for (h = e.length; h--;)e[h]._dist > j && e.splice(h, 1); + if (e.length && e[0].plotX !== this.hoverX)b.tooltip.refresh(e, + a), this.hoverX = e[0].plotX + } + if (g && g.tracker && (d = g.tooltipPoints[k]) && d !== f)d.onMouseOver() + }, resetTracker: function (a) { + var b = this.chart, c = b.hoverSeries, d = b.hoverPoint, e = b.hoverPoints || d, b = b.tooltip; + (a = a && b && e) && na(e)[0].plotX === A && (a = !1); + if (a)b.refresh(e); else { + if (d)d.onMouseOut(); + if (c)c.onMouseOut(); + b && (b.hide(), b.hideCrosshairs()); + this.hoverX = null + } + }, setDOMEvents: function () { + function a() { + if (b.selectionMarker) { + var f = {xAxis: [], yAxis: []}, g = b.selectionMarker.getBBox(), h = g.x - c.plotLeft, l = g.y - c.plotTop, m; + e && + (n(c.axes, function (a) { + if (a.options.zoomEnabled !== !1) { + var b = a.isXAxis, d = c.inverted ? !b : b, e = a.translate(d ? h : c.plotHeight - l - g.height, !0, 0, 0, 1), d = a.translate(d ? h + g.width : c.plotHeight - l, !0, 0, 0, 1); + !isNaN(e) && !isNaN(d) && (f[b ? "xAxis" : "yAxis"].push({axis: a, min: O(e, d), max: x(e, d)}), m = !0) + } + }), m && E(c, "selection", f, function (a) { + c.zoom(a) + })); + b.selectionMarker = b.selectionMarker.destroy() + } + if (c)F(d, {cursor: "auto"}), c.cancelClick = e, c.mouseIsDown = e = !1; + P(B, ea ? "touchend" : "mouseup", a) + } + + var b = this, c = b.chart, d = c.container, e, + f = b.zoomX && !c.inverted || b.zoomY && c.inverted, g = b.zoomY && !c.inverted || b.zoomX && c.inverted; + b.hideTooltipOnMouseMove = function (a) { + Kb(a); + b.chartPosition && c.hoverSeries && c.hoverSeries.isCartesian && !c.isInsidePlot(a.pageX - b.chartPosition.left - c.plotLeft, a.pageY - b.chartPosition.top - c.plotTop) && b.resetTracker() + }; + b.hideTooltipOnMouseLeave = function () { + b.resetTracker(); + b.chartPosition = null + }; + d.onmousedown = function (d) { + d = b.normalizeMouseEvent(d); + !ea && d.preventDefault && d.preventDefault(); + c.mouseIsDown = !0; + c.cancelClick = !1; + c.mouseDownX = b.mouseDownX = d.chartX; + b.mouseDownY = d.chartY; + I(B, ea ? "touchend" : "mouseup", a) + }; + var h = function (a) { + if (!a || !(a.touches && a.touches.length > 1)) { + a = b.normalizeMouseEvent(a); + if (!ea)a.returnValue = !1; + var d = a.chartX, h = a.chartY, l = !c.isInsidePlot(d - c.plotLeft, h - c.plotTop); + ea && a.type === "touchstart" && (z(a.target, "isTracker") ? c.runTrackerClick || a.preventDefault() : !c.runChartClick && !l && a.preventDefault()); + if (l)d < c.plotLeft ? d = c.plotLeft : d > c.plotLeft + c.plotWidth && (d = c.plotLeft + c.plotWidth), h < c.plotTop ? h = + c.plotTop : h > c.plotTop + c.plotHeight && (h = c.plotTop + c.plotHeight); + if (c.mouseIsDown && a.type !== "touchstart") { + if (e = Math.sqrt(Math.pow(b.mouseDownX - d, 2) + Math.pow(b.mouseDownY - h, 2)), e > 10) { + a = c.isInsidePlot(b.mouseDownX - c.plotLeft, b.mouseDownY - c.plotTop); + if (c.hasCartesianSeries && (b.zoomX || b.zoomY) && a && !b.selectionMarker)b.selectionMarker = c.renderer.rect(c.plotLeft, c.plotTop, f ? 1 : c.plotWidth, g ? 1 : c.plotHeight, 0).attr({fill: b.options.chart.selectionMarkerFill || "rgba(69,114,167,0.25)", zIndex: 7}).add(); + if (b.selectionMarker && + f) { + var m = d - b.mouseDownX; + b.selectionMarker.attr({width: M(m), x: (m > 0 ? 0 : m) + b.mouseDownX}) + } + b.selectionMarker && g && (h -= b.mouseDownY, b.selectionMarker.attr({height: M(h), y: (h > 0 ? 0 : h) + b.mouseDownY})); + a && !b.selectionMarker && b.options.chart.panning && c.pan(d) + } + } else if (!l)b.onmousemove(a); + return l || !c.hasCartesianSeries + } + }; + d.onmousemove = h; + I(d, "mouseleave", b.hideTooltipOnMouseLeave); + I(B, "mousemove", b.hideTooltipOnMouseMove); + d.ontouchstart = function (a) { + if (b.zoomX || b.zoomY)d.onmousedown(a); + h(a) + }; + d.ontouchmove = h; + d.ontouchend = + function () { + e && b.resetTracker() + }; + d.onclick = function (a) { + var d = c.hoverPoint, e, f, a = b.normalizeMouseEvent(a); + a.cancelBubble = !0; + if (!c.cancelClick)d && (z(a.target, "isTracker") || z(a.target.parentNode, "isTracker")) ? (e = d.plotX, f = d.plotY, u(d, {pageX: b.chartPosition.left + c.plotLeft + (c.inverted ? c.plotWidth - f : e), pageY: b.chartPosition.top + c.plotTop + (c.inverted ? c.plotHeight - e : f)}), E(d.series, "click", u(a, {point: d})), d.firePointEvent("click", a)) : (u(a, b.getMouseCoordinates(a)), c.isInsidePlot(a.chartX - c.plotLeft, a.chartY - + c.plotTop) && E(c, "click", a)) + } + }, destroy: function () { + var a = this.chart, b = a.container; + if (a.trackerGroup)a.trackerGroup = a.trackerGroup.destroy(); + P(b, "mouseleave", this.hideTooltipOnMouseLeave); + P(B, "mousemove", this.hideTooltipOnMouseMove); + b.onclick = b.onmousedown = b.onmousemove = b.ontouchstart = b.ontouchend = b.ontouchmove = null; + clearInterval(this.tooltipInterval) + }, init: function (a, b) { + if (!a.trackerGroup)a.trackerGroup = a.renderer.g("tracker").attr({zIndex: 9}).add(); + if (b.enabled)a.tooltip = new pb(a, b), this.tooltipInterval = + setInterval(function () { + a.tooltip.tick() + }, 32); + this.setDOMEvents() + }}; + qb.prototype = {init: function (a) { + var b = this, c = b.options = a.options.legend; + if (c.enabled) { + var d = c.itemStyle, e = o(c.padding, 8), f = c.itemMarginTop || 0; + b.baseline = w(d.fontSize) + 3 + f; + b.itemStyle = d; + b.itemHiddenStyle = C(d, c.itemHiddenStyle); + b.itemMarginTop = f; + b.padding = e; + b.initialItemX = e; + b.initialItemY = e - 5; + b.maxItemWidth = 0; + b.chart = a; + b.itemHeight = 0; + b.lastLineHeight = 0; + b.render(); + I(b.chart, "endResize", function () { + b.positionCheckboxes() + }) + } + }, colorizeItem: function (a, b) { + var c = this.options, d = a.legendItem, e = a.legendLine, f = a.legendSymbol, g = this.itemHiddenStyle.color, c = b ? c.itemStyle.color : g, g = b ? a.color : g; + d && d.css({fill: c}); + e && e.attr({stroke: g}); + f && f.attr({stroke: g, fill: g}) + }, positionItem: function (a) { + var b = this.options, c = b.symbolPadding, b = !b.rtl, d = a._legendItemPos, e = d[0], d = d[1], f = a.checkbox; + a.legendGroup && a.legendGroup.translate(b ? e : this.legendWidth - e - 2 * c - 4, d); + if (f)f.x = e, f.y = d + }, destroyItem: function (a) { + var b = a.checkbox; + n(["legendItem", "legendLine", "legendSymbol", "legendGroup"], + function (b) { + a[b] && a[b].destroy() + }); + b && Qa(a.checkbox) + }, destroy: function () { + var a = this.group, b = this.box; + if (b)this.box = b.destroy(); + if (a)this.group = a.destroy() + }, positionCheckboxes: function () { + var a = this; + n(a.allItems, function (b) { + var c = b.checkbox, d = a.group.alignAttr; + c && F(c, {left: d.translateX + b.legendItemWidth + c.x - 20 + "px", top: d.translateY + c.y + 3 + "px"}) + }) + }, renderItem: function (a) { + var q; + var b = this, c = b.chart, d = c.renderer, e = b.options, f = e.layout === "horizontal", g = e.symbolWidth, h = e.symbolPadding, i = b.itemStyle, j = b.itemHiddenStyle, + k = b.padding, l = !e.rtl, m = e.width, p = e.itemMarginBottom || 0, n = b.itemMarginTop, o = b.initialItemX, r = a.legendItem, s = a.series || a, t = s.options, u = t.showCheckbox; + if (!r && (a.legendGroup = d.g("legend-item").attr({zIndex: 1}).add(b.scrollGroup), s.drawLegendSymbol(b, a), a.legendItem = r = d.text(e.labelFormatter.call(a), l ? g + h : -h, b.baseline, e.useHTML).css(C(a.visible ? i : j)).attr({align: l ? "left" : "right", zIndex: 2}).add(a.legendGroup), a.legendGroup.on("mouseover",function () { + a.setState("hover"); + r.css(b.options.itemHoverStyle) + }).on("mouseout", + function () { + r.css(a.visible ? i : j); + a.setState() + }).on("click", function (b) { + var c = function () { + a.setVisible() + }, b = {browserEvent: b}; + a.firePointEvent ? a.firePointEvent("legendItemClick", b, c) : E(a, "legendItemClick", b, c) + }), b.colorizeItem(a, a.visible), t && u))a.checkbox = S("input", {type: "checkbox", checked: a.selected, defaultChecked: a.selected}, e.itemCheckboxStyle, c.container), I(a.checkbox, "click", function (b) { + E(a, "checkboxClick", {checked: b.target.checked}, function () { + a.select() + }) + }); + d = r.getBBox(); + q = a.legendItemWidth = e.itemWidth || + g + h + d.width + k + (u ? 20 : 0), e = q; + b.itemHeight = g = d.height; + if (f && b.itemX - o + e > (m || c.chartWidth - 2 * k - o))b.itemX = o, b.itemY += n + b.lastLineHeight + p, b.lastLineHeight = 0; + b.maxItemWidth = x(b.maxItemWidth, e); + b.lastItemY = n + b.itemY + p; + b.lastLineHeight = x(g, b.lastLineHeight); + a._legendItemPos = [b.itemX, b.itemY]; + f ? b.itemX += e : (b.itemY += n + g + p, b.lastLineHeight = g); + b.offsetWidth = m || x(f ? b.itemX - o : e, b.offsetWidth) + }, render: function () { + var a = this, b = a.chart, c = b.renderer, d = a.group, e, f, g, h, i = a.box, j = a.options, k = a.padding, l = j.borderWidth, + m = j.backgroundColor; + a.itemX = a.initialItemX; + a.itemY = a.initialItemY; + a.offsetWidth = 0; + a.lastItemY = 0; + if (!d)a.group = d = c.g("legend").attr({zIndex: 7}).add(), a.contentGroup = c.g().attr({zIndex: 1}).add(d), a.scrollGroup = c.g().add(a.contentGroup), a.clipRect = c.clipRect(0, 0, 9999, b.chartHeight), a.contentGroup.clip(a.clipRect); + e = []; + n(b.series, function (a) { + var b = a.options; + b.showInLegend && (e = e.concat(a.legendItems || (b.legendType === "point" ? a.data : a))) + }); + Qb(e, function (a, b) { + return(a.options.legendIndex || 0) - (b.options.legendIndex || + 0) + }); + j.reversed && e.reverse(); + a.allItems = e; + a.display = f = !!e.length; + n(e, function (b) { + a.renderItem(b) + }); + g = j.width || a.offsetWidth; + h = a.lastItemY + a.lastLineHeight; + h = a.handleOverflow(h); + if (l || m) { + g += k; + h += k; + if (i) { + if (g > 0 && h > 0)i[i.isNew ? "attr" : "animate"](i.crisp(null, null, null, g, h)), i.isNew = !1 + } else a.box = i = c.rect(0, 0, g, h, j.borderRadius, l || 0).attr({stroke: j.borderColor, "stroke-width": l || 0, fill: m || U}).add(d).shadow(j.shadow), i.isNew = !0; + i[f ? "show" : "hide"]() + } + a.legendWidth = g; + a.legendHeight = h; + n(e, function (b) { + a.positionItem(b) + }); + f && d.align(u({width: g, height: h}, j), !0, b.spacingBox); + b.isResizing || this.positionCheckboxes() + }, handleOverflow: function (a) { + var b = this, c = this.chart, d = c.renderer, e = this.options, f = e.y, f = c.spacingBox.height + (e.verticalAlign === "top" ? -f : f) - this.padding, g = e.maxHeight, h = this.clipRect, i = e.navigation, j = o(i.animation, !0), k = i.arrowSize || 12, l = this.nav; + e.layout === "horizontal" && (f /= 2); + g && (f = O(f, g)); + if (a > f) { + this.clipHeight = c = f - 20; + this.pageCount = wa(a / c); + this.currentPage = o(this.currentPage, 1); + this.fullHeight = a; + h.attr({height: c}); + if (!l)this.nav = l = d.g().attr({zIndex: 1}).add(this.group), this.up = d.symbol("triangle", 0, 0, k, k).on("click",function () { + b.scroll(-1, j) + }).add(l), this.pager = d.text("", 15, 10).css(i.style).add(l), this.down = d.symbol("triangle-down", 0, 0, k, k).on("click",function () { + b.scroll(1, j) + }).add(l); + b.scroll(0); + a = f + } else l && (h.attr({height: c.chartHeight}), l.hide(), this.scrollGroup.attr({translateY: 1})); + return a + }, scroll: function (a, b) { + var c = this.pageCount, d = this.currentPage + a, e = this.clipHeight, f = this.options.navigation, g = f.activeColor, + f = f.inactiveColor, h = this.pager, i = this.padding; + d > c && (d = c); + if (d > 0)b !== A && ua(b, this.chart), this.nav.attr({translateX: i, translateY: e + 7, visibility: "visible"}), this.up.attr({fill: d === 1 ? f : g}).css({cursor: d === 1 ? "default" : "pointer"}), h.attr({text: d + "/" + this.pageCount}), this.down.attr({x: 18 + this.pager.getBBox().width, fill: d === c ? f : g}).css({cursor: d === c ? "default" : "pointer"}), this.scrollGroup.animate({translateY: -O(e * (d - 1), this.fullHeight - e + i) + 1}), h.attr({text: d + "/" + c}), this.currentPage = d + }}; + rb.prototype = {initSeries: function (a) { + var b = + this.options.chart, b = new Y[a.type || b.type || b.defaultSeriesType]; + b.init(this, a); + return b + }, addSeries: function (a, b, c) { + var d = this; + a && (ua(c, d), b = o(b, !0), E(d, "addSeries", {options: a}, function () { + d.initSeries(a); + d.isDirtyLegend = !0; + b && d.redraw() + })) + }, isInsidePlot: function (a, b) { + return a >= 0 && a <= this.plotWidth && b >= 0 && b <= this.plotHeight + }, adjustTickAmounts: function () { + this.options.chart.alignTicks !== !1 && n(this.axes, function (a) { + a.adjustTickAmount() + }); + this.maxTicks = null + }, redraw: function (a) { + var b = this.axes, c = this.series, + d = this.tracker, e = this.legend, f = this.isDirtyLegend, g, h = this.isDirtyBox, i = c.length, j = i, k = this.clipRect, l = this.renderer, m = l.isHidden(); + ua(a, this); + for (m && this.cloneRenderTo(); j--;)if (a = c[j], a.isDirty && a.options.stacking) { + g = !0; + break + } + if (g)for (j = i; j--;)if (a = c[j], a.options.stacking)a.isDirty = !0; + n(c, function (a) { + a.isDirty && a.options.legendType === "point" && (f = !0) + }); + if (f && e.options.enabled)e.render(), this.isDirtyLegend = !1; + if (this.hasCartesianSeries) { + if (!this.isResizing)this.maxTicks = null, n(b, function (a) { + a.setScale() + }); + this.adjustTickAmounts(); + this.getMargins(); + n(b, function (a) { + if (a.isDirtyExtremes)a.isDirtyExtremes = !1, E(a, "afterSetExtremes", a.getExtremes()); + if (a.isDirty || h || g)a.redraw(), h = !0 + }) + } + h && (this.drawChartBox(), k && (Fa(k), k.animate({width: this.plotSizeX, height: this.plotSizeY + 1}))); + n(c, function (a) { + a.isDirty && a.visible && (!a.isCartesian || a.xAxis) && a.redraw() + }); + d && d.resetTracker && d.resetTracker(!0); + l.draw(); + E(this, "redraw"); + m && this.cloneRenderTo(!0) + }, showLoading: function (a) { + var b = this.options, c = this.loadingDiv, + d = b.loading; + if (!c)this.loadingDiv = c = S(ia, {className: "highcharts-loading"}, u(d.style, {left: this.plotLeft + "px", top: this.plotTop + "px", width: this.plotWidth + "px", height: this.plotHeight + "px", zIndex: 10, display: U}), this.container), this.loadingSpan = S("span", null, d.labelStyle, c); + this.loadingSpan.innerHTML = a || b.lang.loading; + if (!this.loadingShown)F(c, {opacity: 0, display: ""}), eb(c, {opacity: d.style.opacity}, {duration: d.showDuration || 0}), this.loadingShown = !0 + }, hideLoading: function () { + var a = this.options, b = this.loadingDiv; + b && eb(b, {opacity: 0}, {duration: a.loading.hideDuration || 100, complete: function () { + F(b, {display: U}) + }}); + this.loadingShown = !1 + }, get: function (a) { + var b = this.axes, c = this.series, d, e; + for (d = 0; d < b.length; d++)if (b[d].options.id === a)return b[d]; + for (d = 0; d < c.length; d++)if (c[d].options.id === a)return c[d]; + for (d = 0; d < c.length; d++) { + e = c[d].points || []; + for (b = 0; b < e.length; b++)if (e[b].id === a)return e[b] + } + return null + }, getAxes: function () { + var a = this, b = this.options, c = b.xAxis || {}, b = b.yAxis || {}, c = na(c); + n(c, function (a, b) { + a.index = b; + a.isX = !0 + }); + b = na(b); + n(b, function (a, b) { + a.index = b + }); + c = c.concat(b); + n(c, function (b) { + new ob(a, b) + }); + a.adjustTickAmounts() + }, getSelectedPoints: function () { + var a = []; + n(this.series, function (b) { + a = a.concat(ub(b.points, function (a) { + return a.selected + })) + }); + return a + }, getSelectedSeries: function () { + return ub(this.series, function (a) { + return a.selected + }) + }, showResetZoom: function () { + var a = this, b = V.lang, c = a.options.chart.resetZoomButton, d = c.theme, e = d.states, f = c.relativeTo === "chart" ? null : {x: a.plotLeft, y: a.plotTop, width: a.plotWidth, height: a.plotHeight}; + this.resetZoomButton = a.renderer.button(b.resetZoom, null, null,function () { + a.zoomOut() + }, d, e && e.hover).attr({align: c.position.align, title: b.resetZoomTitle}).add().align(c.position, !1, f) + }, zoomOut: function () { + var a = this, b = a.resetZoomButton; + E(a, "selection", {resetSelection: !0}, function () { + a.zoom() + }); + if (b)a.resetZoomButton = b.destroy() + }, zoom: function (a) { + var b = this, c = b.options.chart, d; + b.resetZoomEnabled !== !1 && !b.resetZoomButton && b.showResetZoom(); + !a || a.resetSelection ? n(b.axes, function (a) { + a.options.zoomEnabled !== !1 && (a.setExtremes(null, null, !1), d = !0) + }) : n(a.xAxis.concat(a.yAxis), function (a) { + var c = a.axis; + if (b.tracker[c.isXAxis ? "zoomX" : "zoomY"])c.setExtremes(a.min, a.max, !1), d = !0 + }); + d && b.redraw(o(c.animation, b.pointCount < 100)) + }, pan: function (a) { + var b = this.xAxis[0], c = this.mouseDownX, d = b.pointRange / 2, e = b.getExtremes(), f = b.translate(c - a, !0) + d, c = b.translate(c + this.plotWidth - a, !0) - d; + (d = this.hoverPoints) && n(d, function (a) { + a.setState() + }); + b.series.length && f > O(e.dataMin, e.min) && c < x(e.dataMax, e.max) && b.setExtremes(f, c, !0, + !1); + this.mouseDownX = a; + F(this.container, {cursor: "move"}) + }, setTitle: function (a, b) { + var c = this, d = c.options, e; + c.chartTitleOptions = e = C(d.title, a); + c.chartSubtitleOptions = d = C(d.subtitle, b); + n([ + ["title", a, e], + ["subtitle", b, d] + ], function (a) { + var b = a[0], d = c[b], e = a[1], a = a[2]; + d && e && (d = d.destroy()); + a && a.text && !d && (c[b] = c.renderer.text(a.text, 0, 0, a.useHTML).attr({align: a.align, "class": "highcharts-" + b, zIndex: a.zIndex || 4}).css(a.style).add().align(a, !1, c.spacingBox)) + }) + }, getChartSize: function () { + var a = this.options.chart, + b = this.renderToClone || this.renderTo; + this.containerWidth = Va(b, "width"); + this.containerHeight = Va(b, "height"); + this.chartWidth = a.width || this.containerWidth || 600; + this.chartHeight = a.height || (this.containerHeight > 19 ? this.containerHeight : 400) + }, cloneRenderTo: function (a) { + var b = this.renderToClone, c = this.container; + a ? b && (this.renderTo.appendChild(c), Qa(b), delete this.renderToClone) : (c && this.renderTo.removeChild(c), this.renderToClone = b = this.renderTo.cloneNode(0), F(b, {position: "absolute", top: "-9999px", display: "block"}), + B.body.appendChild(b), c && b.appendChild(c)) + }, getContainer: function () { + var a, b = this.options.chart, c, d, e; + this.renderTo = a = b.renderTo; + e = "highcharts-" + sb++; + if (ra(a))this.renderTo = a = B.getElementById(a); + a || mb(13, !0); + a.innerHTML = ""; + a.offsetWidth || this.cloneRenderTo(); + this.getChartSize(); + c = this.chartWidth; + d = this.chartHeight; + this.container = a = S(ia, {className: "highcharts-container" + (b.className ? " " + b.className : ""), id: e}, u({position: "relative", overflow: "hidden", width: c + "px", height: d + "px", textAlign: "left", lineHeight: "normal"}, + b.style), this.renderToClone || a); + this.renderer = b.forExport ? new qa(a, c, d, !0) : new Ta(a, c, d); + ga && this.renderer.create(this, a, c, d) + }, getMargins: function () { + var a = this.options.chart, b = a.spacingTop, c = a.spacingRight, d = a.spacingBottom, a = a.spacingLeft, e, f = this.legend, g = this.optionsMarginTop, h = this.optionsMarginLeft, i = this.optionsMarginRight, j = this.optionsMarginBottom, k = this.chartTitleOptions, l = this.chartSubtitleOptions, m = this.options.legend, p = o(m.margin, 10), q = m.x, t = m.y, r = m.align, y = m.verticalAlign; + this.resetMargins(); + e = this.axisOffset; + if ((this.title || this.subtitle) && !s(this.optionsMarginTop))if (l = x(this.title && !k.floating && !k.verticalAlign && k.y || 0, this.subtitle && !l.floating && !l.verticalAlign && l.y || 0))this.plotTop = x(this.plotTop, l + o(k.margin, 15) + b); + if (f.display && !m.floating)if (r === "right") { + if (!s(i))this.marginRight = x(this.marginRight, f.legendWidth - q + p + c) + } else if (r === "left") { + if (!s(h))this.plotLeft = x(this.plotLeft, f.legendWidth + q + p + a) + } else if (y === "top") { + if (!s(g))this.plotTop = x(this.plotTop, f.legendHeight + t + p + b) + } else if (y === + "bottom" && !s(j))this.marginBottom = x(this.marginBottom, f.legendHeight - t + p + d); + this.extraBottomMargin && (this.marginBottom += this.extraBottomMargin); + this.extraTopMargin && (this.plotTop += this.extraTopMargin); + this.hasCartesianSeries && n(this.axes, function (a) { + a.getOffset() + }); + s(h) || (this.plotLeft += e[3]); + s(g) || (this.plotTop += e[0]); + s(j) || (this.marginBottom += e[2]); + s(i) || (this.marginRight += e[1]); + this.setChartSize() + }, initReflow: function () { + function a(a) { + var g = c.width || Va(d, "width"), h = c.height || Va(d, "height"), a = a ? + a.target : N; + if (g && h && (a === N || a === B)) { + if (g !== b.containerWidth || h !== b.containerHeight)clearTimeout(e), e = setTimeout(function () { + b.resize(g, h, !1) + }, 100); + b.containerWidth = g; + b.containerHeight = h + } + } + + var b = this, c = b.options.chart, d = b.renderTo, e; + I(N, "resize", a); + I(b, "destroy", function () { + P(N, "resize", a) + }) + }, fireEndResize: function () { + var a = this; + a && E(a, "endResize", null, function () { + a.isResizing -= 1 + }) + }, resize: function (a, b, c) { + var d, e, f = this.title, g = this.subtitle; + this.isResizing += 1; + ua(c, this); + this.oldChartHeight = this.chartHeight; + this.oldChartWidth = this.chartWidth; + if (s(a))this.chartWidth = d = t(a); + if (s(b))this.chartHeight = e = t(b); + F(this.container, {width: d + "px", height: e + "px"}); + this.renderer.setSize(d, e, c); + this.plotWidth = d - this.plotLeft - this.marginRight; + this.plotHeight = e - this.plotTop - this.marginBottom; + this.maxTicks = null; + n(this.axes, function (a) { + a.isDirty = !0; + a.setScale() + }); + n(this.series, function (a) { + a.isDirty = !0 + }); + this.isDirtyBox = this.isDirtyLegend = !0; + this.getMargins(); + a = this.spacingBox; + f && f.align(null, null, a); + g && g.align(null, null, + a); + this.redraw(c); + this.oldChartHeight = null; + E(this, "resize"); + Ra === !1 ? this.fireEndResize() : setTimeout(this.fireEndResize, Ra && Ra.duration || 500) + }, setChartSize: function () { + var a = this.inverted, b = this.chartWidth, c = this.chartHeight, d = this.options.chart, e = d.spacingTop, f = d.spacingRight, g = d.spacingBottom, d = d.spacingLeft; + this.plotLeft = t(this.plotLeft); + this.plotTop = t(this.plotTop); + this.plotWidth = t(b - this.plotLeft - this.marginRight); + this.plotHeight = t(c - this.plotTop - this.marginBottom); + this.plotSizeX = a ? this.plotHeight : + this.plotWidth; + this.plotSizeY = a ? this.plotWidth : this.plotHeight; + this.spacingBox = {x: d, y: e, width: b - d - f, height: c - e - g}; + n(this.axes, function (a) { + a.setAxisSize(); + a.setAxisTranslation() + }) + }, resetMargins: function () { + var a = this.options.chart, b = a.spacingRight, c = a.spacingBottom, d = a.spacingLeft; + this.plotTop = o(this.optionsMarginTop, a.spacingTop); + this.marginRight = o(this.optionsMarginRight, b); + this.marginBottom = o(this.optionsMarginBottom, c); + this.plotLeft = o(this.optionsMarginLeft, d); + this.axisOffset = [0, 0, 0, 0] + }, drawChartBox: function () { + var a = + this.options.chart, b = this.renderer, c = this.chartWidth, d = this.chartHeight, e = this.chartBackground, f = this.plotBackground, g = this.plotBorder, h = this.plotBGImage, i = a.borderWidth || 0, j = a.backgroundColor, k = a.plotBackgroundColor, l = a.plotBackgroundImage, m, p = {x: this.plotLeft, y: this.plotTop, width: this.plotWidth, height: this.plotHeight}; + m = i + (a.shadow ? 8 : 0); + if (i || j)if (e)e.animate(e.crisp(null, null, null, c - m, d - m)); else { + e = {fill: j || U}; + if (i)e.stroke = a.borderColor, e["stroke-width"] = i; + this.chartBackground = b.rect(m / 2, m / 2, c - + m, d - m, a.borderRadius, i).attr(e).add().shadow(a.shadow) + } + if (k)f ? f.animate(p) : this.plotBackground = b.rect(this.plotLeft, this.plotTop, this.plotWidth, this.plotHeight, 0).attr({fill: k}).add().shadow(a.plotShadow); + if (l)h ? h.animate(p) : this.plotBGImage = b.image(l, this.plotLeft, this.plotTop, this.plotWidth, this.plotHeight).add(); + if (a.plotBorderWidth)g ? g.animate(g.crisp(null, this.plotLeft, this.plotTop, this.plotWidth, this.plotHeight)) : this.plotBorder = b.rect(this.plotLeft, this.plotTop, this.plotWidth, this.plotHeight, + 0, a.plotBorderWidth).attr({stroke: a.plotBorderColor, "stroke-width": a.plotBorderWidth, zIndex: 4}).add(); + this.isDirtyBox = !1 + }, propFromSeries: function () { + var a = this, b = a.options.chart, c, d = a.options.series, e, f; + n(["inverted", "angular", "polar"], function (g) { + c = Y[b.type || b.defaultSeriesType]; + f = a[g] || b[g] || c && c.prototype[g]; + for (e = d && d.length; !f && e--;)(c = Y[d[e].type]) && c.prototype[g] && (f = !0); + a[g] = f + }) + }, render: function () { + var a = this, b = a.axes, c = a.renderer, d = a.options, e = d.labels, d = d.credits, f; + a.setTitle(); + a.legend = new qb(a); + n(b, function (a) { + a.setScale() + }); + a.getMargins(); + a.maxTicks = null; + n(b, function (a) { + a.setTickPositions(!0); + a.setMaxTicks() + }); + a.adjustTickAmounts(); + a.getMargins(); + a.drawChartBox(); + a.hasCartesianSeries && n(b, function (a) { + a.render() + }); + if (!a.seriesGroup)a.seriesGroup = c.g("series-group").attr({zIndex: 3}).add(); + n(a.series, function (a) { + a.translate(); + a.setTooltipPoints(); + a.render() + }); + e.items && n(e.items, function () { + var b = u(e.style, this.style), d = w(b.left) + a.plotLeft, f = w(b.top) + a.plotTop + 12; + delete b.left; + delete b.top; + c.text(this.html, d, f).attr({zIndex: 2}).css(b).add() + }); + if (d.enabled && !a.credits)f = d.href, a.credits = c.text(d.text, 0, 0).on("click",function () { + if (f)location.href = f + }).attr({align: d.position.align, zIndex: 8}).css(d.style).add().align(d.position); + a.hasRendered = !0 + }, destroy: function () { + var a = this, b = a.axes, c = a.series, d = a.container, e, f = d && d.parentNode; + if (a !== null) { + E(a, "destroy"); + P(a); + for (e = b.length; e--;)b[e] = b[e].destroy(); + for (e = c.length; e--;)c[e] = c[e].destroy(); + n("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,tracker,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","), + function (b) { + var c = a[b]; + c && (a[b] = c.destroy()) + }); + if (d)d.innerHTML = "", P(d), f && Qa(d), d = null; + for (e in a)delete a[e]; + a = a.options = null + } + }, firstRender: function () { + var a = this, b = a.options, c = a.callback; + if (!Da && N == N.top && B.readyState !== "complete" || ga && !N.canvg)ga ? Nb.push(function () { + a.firstRender() + }, b.global.canvasToolsURL) : B.attachEvent("onreadystatechange", function () { + B.detachEvent("onreadystatechange", a.firstRender); + B.readyState === "complete" && a.firstRender() + }); else { + a.getContainer(); + E(a, "init"); + if (Highcharts.RangeSelector && + b.rangeSelector.enabled)a.rangeSelector = new Highcharts.RangeSelector(a); + a.resetMargins(); + a.setChartSize(); + a.propFromSeries(); + a.getAxes(); + n(b.series || [], function (b) { + a.initSeries(b) + }); + if (Highcharts.Scroller && (b.navigator.enabled || b.scrollbar.enabled))a.scroller = new Highcharts.Scroller(a); + a.tracker = new Db(a, b); + a.render(); + a.renderer.draw(); + c && c.apply(a, [a]); + n(a.callbacks, function (b) { + b.apply(a, [a]) + }); + a.cloneRenderTo(!0); + E(a, "load") + } + }, init: function (a) { + var b = this.options.chart, c; + b.reflow !== !1 && I(this, "load", + this.initReflow); + if (a)for (c in a)I(this, c, a[c]); + this.xAxis = []; + this.yAxis = []; + this.animation = ga ? !1 : o(b.animation, !0); + this.setSize = this.resize; + this.pointCount = 0; + this.counters = new Ab; + this.firstRender() + }}; + rb.prototype.callbacks = []; + var Wa = function () { + }; + Wa.prototype = {init: function (a, b, c) { + var d = a.chart.counters; + this.series = a; + this.applyOptions(b, c); + this.pointAttr = {}; + if (a.options.colorByPoint) { + b = a.chart.options.colors; + if (!this.options)this.options = {}; + this.color = this.options.color = this.color || b[d.color++]; + d.wrapColor(b.length) + } + a.chart.pointCount++; + return this + }, applyOptions: function (a, b) { + var c = this.series, d = typeof a; + this.config = a; + if (d === "number" || a === null)this.y = a; else if (typeof a[0] === "number")this.x = a[0], this.y = a[1]; else if (d === "object" && typeof a.length !== "number") { + if (u(this, a), this.options = a, a.dataLabels)c._hasPointLabels = !0 + } else if (typeof a[0] === "string")this.name = a[0], this.y = a[1]; + if (this.x === A)this.x = b === A ? c.autoIncrement() : b + }, destroy: function () { + var a = this.series.chart, b = a.hoverPoints, c; + a.pointCount--; + if (b && (this.setState(), za(b, this), + !b.length))a.hoverPoints = null; + if (this === a.hoverPoint)this.onMouseOut(); + if (this.graphic || this.dataLabel)P(this), this.destroyElements(); + this.legendItem && a.legend.destroyItem(this); + for (c in this)this[c] = null + }, destroyElements: function () { + for (var a = "graphic,tracker,dataLabel,group,connector,shadowGroup".split(","), b, c = 6; c--;)b = a[c], this[b] && (this[b] = this[b].destroy()) + }, getLabelConfig: function () { + return{x: this.category, y: this.y, key: this.name || this.category, series: this.series, point: this, percentage: this.percentage, + total: this.total || this.stackTotal} + }, select: function (a, b) { + var c = this, d = c.series.chart, a = o(a, !c.selected); + c.firePointEvent(a ? "select" : "unselect", {accumulate: b}, function () { + c.selected = a; + c.setState(a && "select"); + b || n(d.getSelectedPoints(), function (a) { + if (a.selected && a !== c)a.selected = !1, a.setState(""), a.firePointEvent("unselect") + }) + }) + }, onMouseOver: function () { + var a = this.series, b = a.chart, c = b.tooltip, d = b.hoverPoint; + if (d && d !== this)d.onMouseOut(); + this.firePointEvent("mouseOver"); + c && (!c.shared || a.noSharedTooltip) && + c.refresh(this); + this.setState("hover"); + b.hoverPoint = this + }, onMouseOut: function () { + this.firePointEvent("mouseOut"); + this.setState(); + this.series.chart.hoverPoint = null + }, tooltipFormatter: function (a) { + var b = this.series, c = b.tooltipOptions, d = a.match(/\{(series|point)\.[a-zA-Z]+\}/g), e = /[{\.}]/, f, g, h, i, j = {y: 0, open: 0, high: 0, low: 0, close: 0, percentage: 1, total: 1}; + c.valuePrefix = c.valuePrefix || c.yPrefix; + c.valueDecimals = c.valueDecimals || c.yDecimals; + c.valueSuffix = c.valueSuffix || c.ySuffix; + for (i in d)g = d[i], ra(g) && g !== + a && (h = (" " + g).split(e), f = {point: this, series: b}[h[1]], h = h[2], f === this && j.hasOwnProperty(h) ? (f = j[h] ? h : "value", f = (c[f + "Prefix"] || "") + Xa(this[h], o(c[f + "Decimals"], -1)) + (c[f + "Suffix"] || "")) : f = f[h], a = a.replace(g, f)); + return a + }, update: function (a, b, c) { + var d = this, e = d.series, f = d.graphic, g, h = e.data, i = h.length, j = e.chart, b = o(b, !0); + d.firePointEvent("update", {options: a}, function () { + d.applyOptions(a); + aa(a) && (e.getAttribs(), f && f.attr(d.pointAttr[e.state])); + for (g = 0; g < i; g++)if (h[g] === d) { + e.xData[g] = d.x; + e.yData[g] = d.y; + e.options.data[g] = a; + break + } + e.isDirty = !0; + e.isDirtyData = !0; + b && j.redraw(c) + }) + }, remove: function (a, b) { + var c = this, d = c.series, e = d.chart, f, g = d.data, h = g.length; + ua(b, e); + a = o(a, !0); + c.firePointEvent("remove", null, function () { + for (f = 0; f < h; f++)if (g[f] === c) { + g.splice(f, 1); + d.options.data.splice(f, 1); + d.xData.splice(f, 1); + d.yData.splice(f, 1); + break + } + c.destroy(); + d.isDirty = !0; + d.isDirtyData = !0; + a && e.redraw() + }) + }, firePointEvent: function (a, b, c) { + var d = this, e = this.series.options; + (e.point.events[a] || d.options && d.options.events && d.options.events[a]) && + this.importEvents(); + a === "click" && e.allowPointSelect && (c = function (a) { + d.select(null, a.ctrlKey || a.metaKey || a.shiftKey) + }); + E(this, a, b, c) + }, importEvents: function () { + if (!this.hasImportedEvents) { + var a = C(this.series.options.point, this.options).events, b; + this.events = a; + for (b in a)I(this, b, a[b]); + this.hasImportedEvents = !0 + } + }, setState: function (a) { + var b = this.plotX, c = this.plotY, d = this.series, e = d.options.states, f = Z[d.type].marker && d.options.marker, g = f && !f.enabled, h = f && f.states[a], i = h && h.enabled === !1, j = d.stateMarkerGraphic, + k = d.chart, l = this.pointAttr, a = a || ""; + if (!(a === this.state || this.selected && a !== "select" || e[a] && e[a].enabled === !1 || a && (i || g && !h.enabled))) { + if (this.graphic)e = f && this.graphic.symbolName && l[a].r, this.graphic.attr(C(l[a], e ? {x: b - e, y: c - e, width: 2 * e, height: 2 * e} : {})); else { + if (a && h) { + if (!j)e = h.radius, d.stateMarkerGraphic = j = k.renderer.symbol(d.symbol, -e, -e, 2 * e, 2 * e).attr(l[a]).add(d.group); + j.translate(b, c) + } + if (j)j[a ? "show" : "hide"]() + } + this.state = a + } + }}; + var R = function () { + }; + R.prototype = {isCartesian: !0, type: "line", pointClass: Wa, + sorted: !0, pointAttrToOptions: {stroke: "lineColor", "stroke-width": "lineWidth", fill: "fillColor", r: "radius"}, init: function (a, b) { + var c, d; + d = a.series.length; + this.chart = a; + this.options = b = this.setOptions(b); + this.bindAxes(); + u(this, {index: d, name: b.name || "Series " + (d + 1), state: "", pointAttr: {}, visible: b.visible !== !1, selected: b.selected === !0}); + if (ga)b.animation = !1; + d = b.events; + for (c in d)I(this, c, d[c]); + if (d && d.click || b.point && b.point.events && b.point.events.click || b.allowPointSelect)a.runTrackerClick = !0; + this.getColor(); + this.getSymbol(); + this.setData(b.data, !1); + if (this.isCartesian)a.hasCartesianSeries = !0; + a.series.push(this) + }, bindAxes: function () { + var a = this, b = a.options, c = a.chart, d; + a.isCartesian && n(["xAxis", "yAxis"], function (e) { + n(c[e], function (c) { + d = c.options; + if (b[e] === d.index || b[e] === A && d.index === 0)c.series.push(a), a[e] = c, c.isDirty = !0 + }) + }) + }, autoIncrement: function () { + var a = this.options, b = this.xIncrement, b = o(b, a.pointStart, 0); + this.pointInterval = o(this.pointInterval, a.pointInterval, 1); + this.xIncrement = b + this.pointInterval; + return b + }, getSegments: function () { + var a = -1, b = [], c, d = this.points, e = d.length; + if (e)if (this.options.connectNulls) { + for (c = e; c--;)d[c].y === null && d.splice(c, 1); + d.length && (b = [d]) + } else n(d, function (c, g) { + c.y === null ? (g > a + 1 && b.push(d.slice(a + 1, g)), a = g) : g === e - 1 && b.push(d.slice(a + 1, g + 1)) + }); + this.segments = b + }, setOptions: function (a) { + var b = this.chart.options, c = b.plotOptions, d = a.data; + a.data = null; + c = C(c[this.type], c.series, a); + c.data = a.data = d; + this.tooltipOptions = C(b.tooltip, c.tooltip); + return c + }, getColor: function () { + var a = + this.options, b = this.chart.options.colors, c = this.chart.counters; + this.color = a.color || !a.colorByPoint && b[c.color++] || "gray"; + c.wrapColor(b.length) + }, getSymbol: function () { + var a = this.options.marker, b = this.chart, c = b.options.symbols, b = b.counters; + this.symbol = a.symbol || c[b.symbol++]; + if (/^url/.test(this.symbol))a.radius = 0; + b.wrapSymbol(c.length) + }, drawLegendSymbol: function (a) { + var b = this.options, c = b.marker, d = a.options.symbolWidth, e = this.chart.renderer, f = this.legendGroup, a = a.baseline, g; + if (b.lineWidth) { + g = {"stroke-width": b.lineWidth}; + if (b.dashStyle)g.dashstyle = b.dashStyle; + this.legendLine = e.path(["M", 0, a - 4, "L", d, a - 4]).attr(g).add(f) + } + if (c && c.enabled)b = c.radius, this.legendSymbol = e.symbol(this.symbol, d / 2 - b, a - 4 - b, 2 * b, 2 * b).attr(this.pointAttr[""]).add(f) + }, addPoint: function (a, b, c, d) { + var e = this.data, f = this.graph, g = this.area, h = this.chart, i = this.xData, j = this.yData, k = f && f.shift || 0, l = this.options.data; + ua(d, h); + if (f && c)f.shift = k + 1; + if (g) { + if (c)g.shift = k + 1; + g.isArea = !0 + } + b = o(b, !0); + d = {series: this}; + this.pointClass.prototype.applyOptions.apply(d, [a]); + i.push(d.x); + j.push(this.valueCount === 4 ? [d.open, d.high, d.low, d.close] : d.y); + l.push(a); + c && (e[0] && e[0].remove ? e[0].remove(!1) : (e.shift(), i.shift(), j.shift(), l.shift())); + this.getAttribs(); + this.isDirtyData = this.isDirty = !0; + b && h.redraw() + }, setData: function (a, b) { + var c = this.points, d = this.options, e = this.initialColor, f = this.chart, g = null, h = this.xAxis, i = this.pointClass.prototype; + this.xIncrement = null; + this.pointRange = h && h.categories && 1 || d.pointRange; + if (s(e))f.counters.color = e; + var j = [], k = [], l = a ? a.length : [], m = this.valueCount; + if (l > (d.turboThreshold || 1E3)) { + for (e = 0; g === null && e < l;)g = a[e], e++; + if (Ka(g)) { + i = o(d.pointStart, 0); + d = o(d.pointInterval, 1); + for (e = 0; e < l; e++)j[e] = i, k[e] = a[e], i += d; + this.xIncrement = i + } else if (Ja(g))if (m)for (e = 0; e < l; e++)d = a[e], j[e] = d[0], k[e] = d.slice(1, m + 1); else for (e = 0; e < l; e++)d = a[e], j[e] = d[0], k[e] = d[1] + } else for (e = 0; e < l; e++)d = {series: this}, i.applyOptions.apply(d, [a[e]]), j[e] = d.x, k[e] = i.toYData ? i.toYData.apply(d) : d.y; + this.data = []; + this.options.data = a; + this.xData = j; + this.yData = k; + for (e = c && c.length || 0; e--;)c[e] && c[e].destroy && + c[e].destroy(); + if (h)h.minRange = h.userMinRange; + this.isDirty = this.isDirtyData = f.isDirtyBox = !0; + o(b, !0) && f.redraw(!1) + }, remove: function (a, b) { + var c = this, d = c.chart, a = o(a, !0); + if (!c.isRemoving)c.isRemoving = !0, E(c, "remove", null, function () { + c.destroy(); + d.isDirtyLegend = d.isDirtyBox = !0; + a && d.redraw(b) + }); + c.isRemoving = !1 + }, processData: function (a) { + var b = this.xData, c = this.yData, d = b.length, e = 0, f = d, g, h, i = this.xAxis, j = this.options, k = j.cropThreshold, l = this.isCartesian; + if (l && !this.isDirty && !i.isDirty && !this.yAxis.isDirty && !a)return!1; + if (l && this.sorted && (!k || d > k || this.forceCrop))if (a = i.getExtremes(), i = a.min, k = a.max, b[d - 1] < i || b[0] > k)b = [], c = []; else if (b[0] < i || b[d - 1] > k) { + for (a = 0; a < d; a++)if (b[a] >= i) { + e = x(0, a - 1); + break + } + for (; a < d; a++)if (b[a] > k) { + f = a + 1; + break + } + b = b.slice(e, f); + c = c.slice(e, f); + g = !0 + } + for (a = b.length - 1; a > 0; a--)if (d = b[a] - b[a - 1], d > 0 && (h === A || d < h))h = d; + this.cropped = g; + this.cropStart = e; + this.processedXData = b; + this.processedYData = c; + if (j.pointRange === null)this.pointRange = h || 1; + this.closestPointRange = h + }, generatePoints: function () { + var a = + this.options.data, b = this.data, c, d = this.processedXData, e = this.processedYData, f = this.pointClass, g = d.length, h = this.cropStart || 0, i, j = this.hasGroupedData, k, l = [], m; + if (!b && !j)b = [], b.length = a.length, b = this.data = b; + for (m = 0; m < g; m++)i = h + m, j ? l[m] = (new f).init(this, [d[m]].concat(na(e[m]))) : (b[i] ? k = b[i] : a[i] !== A && (b[i] = k = (new f).init(this, a[i], d[m])), l[m] = k); + if (b && (g !== (c = b.length) || j))for (m = 0; m < c; m++)if (m === h && !j && (m += g), b[m])b[m].destroyElements(), b[m].plotX = A; + this.data = b; + this.points = l + }, translate: function () { + this.processedXData || + this.processData(); + this.generatePoints(); + for (var a = this.chart, b = this.options, c = b.stacking, d = this.xAxis, e = d.categories, f = this.yAxis, g = this.points, h = g.length, i = !!this.modifyValue, j, k = f.series, l = k.length; l--;)if (k[l].visible) { + l === this.index && (j = !0); + break + } + for (l = 0; l < h; l++) { + var k = g[l], m = k.x, p = k.y, n = k.low, o = f.stacks[(p < b.threshold ? "-" : "") + this.stackKey]; + k.plotX = d.translate(m, 0, 0, 0, 1); + if (c && this.visible && o && o[m]) { + n = o[m]; + m = n.total; + n.cum = n = n.cum - p; + p = n + p; + if (j)n = b.threshold; + c === "percent" && (n = m ? n * 100 / m : 0, p = m ? + p * 100 / m : 0); + k.percentage = m ? k.y * 100 / m : 0; + k.stackTotal = m; + k.stackY = p + } + k.yBottom = s(n) ? f.translate(n, 0, 1, 0, 1) : null; + i && (p = this.modifyValue(p, k)); + k.plotY = typeof p === "number" ? t(f.translate(p, 0, 1, 0, 1) * 10) / 10 : A; + k.clientX = a.inverted ? a.plotHeight - k.plotX : k.plotX; + k.category = e && e[k.x] !== A ? e[k.x] : k.x + } + this.getSegments() + }, setTooltipPoints: function (a) { + var b = [], c = this.chart.plotSizeX, d, e; + d = this.xAxis; + var f, g, h = []; + if (this.options.enableMouseTracking !== !1) { + if (a)this.tooltipPoints = null; + n(this.segments || this.points, function (a) { + b = + b.concat(a) + }); + d && d.reversed && (b = b.reverse()); + a = b.length; + for (g = 0; g < a; g++) { + f = b[g]; + d = b[g - 1] ? b[g - 1]._high + 1 : 0; + for (f._high = e = b[g + 1] ? x(0, W((f.plotX + (b[g + 1] ? b[g + 1].plotX : c)) / 2)) : c; d >= 0 && d <= e;)h[d++] = f + } + this.tooltipPoints = h + } + }, tooltipHeaderFormatter: function (a) { + var b = this.tooltipOptions, c = b.xDateFormat, d = this.xAxis, e = d && d.options.type === "datetime", f; + if (e && !c)for (f in D)if (D[f] >= d.closestPointRange) { + c = b.dateTimeLabelFormats[f]; + break + } + return b.headerFormat.replace("{point.key}", e ? db(c, a) : a).replace("{series.name}", + this.name).replace("{series.color}", this.color) + }, onMouseOver: function () { + var a = this.chart, b = a.hoverSeries; + if (ea || !a.mouseIsDown) { + if (b && b !== this)b.onMouseOut(); + this.options.events.mouseOver && E(this, "mouseOver"); + this.setState("hover"); + a.hoverSeries = this + } + }, onMouseOut: function () { + var a = this.options, b = this.chart, c = b.tooltip, d = b.hoverPoint; + if (d)d.onMouseOut(); + this && a.events.mouseOut && E(this, "mouseOut"); + c && !a.stickyTracking && !c.shared && c.hide(); + this.setState(); + b.hoverSeries = null + }, animate: function (a) { + var b = + this.chart, c = this.clipRect, d = this.options.animation; + d && !aa(d) && (d = {}); + if (a) { + if (!c.isAnimating)c.attr("width", 0), c.isAnimating = !0 + } else c.animate({width: b.plotSizeX}, d), this.animate = null + }, drawPoints: function () { + var a, b = this.points, c = this.chart, d, e, f, g, h, i, j, k; + if (this.options.marker.enabled)for (f = b.length; f--;)if (g = b[f], d = g.plotX, e = g.plotY, k = g.graphic, e !== A && !isNaN(e))if (a = g.pointAttr[g.selected ? "select" : ""], h = a.r, i = o(g.marker && g.marker.symbol, this.symbol), j = i.indexOf("url") === 0, k)k.animate(u({x: d - h, + y: e - h}, k.symbolName ? {width: 2 * h, height: 2 * h} : {})); else if (h > 0 || j)g.graphic = c.renderer.symbol(i, d - h, e - h, 2 * h, 2 * h).attr(a).add(this.group) + }, convertAttribs: function (a, b, c, d) { + var e = this.pointAttrToOptions, f, g, h = {}, a = a || {}, b = b || {}, c = c || {}, d = d || {}; + for (f in e)g = e[f], h[f] = o(a[g], b[f], c[f], d[f]); + return h + }, getAttribs: function () { + var a = this, b = Z[a.type].marker ? a.options.marker : a.options, c = b.states, d = c.hover, e, f = a.color, g = {stroke: f, fill: f}, h = a.points || [], i = [], j, k = a.pointAttrToOptions, l; + a.options.marker ? (d.radius = + d.radius || b.radius + 2, d.lineWidth = d.lineWidth || b.lineWidth + 1) : d.color = d.color || pa(d.color || f).brighten(d.brightness).get(); + i[""] = a.convertAttribs(b, g); + n(["hover", "select"], function (b) { + i[b] = a.convertAttribs(c[b], i[""]) + }); + a.pointAttr = i; + for (f = h.length; f--;) { + g = h[f]; + if ((b = g.options && g.options.marker || g.options) && b.enabled === !1)b.radius = 0; + e = !1; + if (g.options)for (l in k)s(b[k[l]]) && (e = !0); + if (e) { + j = []; + c = b.states || {}; + e = c.hover = c.hover || {}; + if (!a.options.marker)e.color = pa(e.color || g.options.color).brighten(e.brightness || + d.brightness).get(); + j[""] = a.convertAttribs(b, i[""]); + j.hover = a.convertAttribs(c.hover, i.hover, j[""]); + j.select = a.convertAttribs(c.select, i.select, j[""]) + } else j = i; + g.pointAttr = j + } + }, destroy: function () { + var a = this, b = a.chart, c = a.clipRect, d = /AppleWebKit\/533/.test(ya), e, f, g = a.data || [], h, i, j; + E(a, "destroy"); + P(a); + n(["xAxis", "yAxis"], function (b) { + if (j = a[b])za(j.series, a), j.isDirty = !0 + }); + a.legendItem && a.chart.legend.destroyItem(a); + for (f = g.length; f--;)(h = g[f]) && h.destroy && h.destroy(); + a.points = null; + if (c && c !== b.clipRect)a.clipRect = + c.destroy(); + n("area,graph,dataLabelsGroup,group,tracker,trackerGroup".split(","), function (b) { + a[b] && (e = d && b === "group" ? "hide" : "destroy", a[b][e]()) + }); + if (b.hoverSeries === a)b.hoverSeries = null; + za(b.series, a); + for (i in a)delete a[i] + }, drawDataLabels: function () { + var a = this, b = a.options, c = b.dataLabels; + if (c.enabled || a._hasPointLabels) { + var d, e, f = a.points, g, h, i, j = a.dataLabelsGroup, k = a.chart, l = a.xAxis, l = l ? l.left : k.plotLeft, m = a.yAxis, m = m ? m.top : k.plotTop, p = k.renderer, q = k.inverted, u = a.type, r = b.stacking, y = u === "column" || + u === "bar", x = c.verticalAlign === null, w = c.y === null, v = p.fontMetrics(c.style.fontSize), H = v.h, J = v.b, K, z; + y && (v = {top: J, middle: J - H / 2, bottom: -H + J}, r ? (x && (c = C(c, {verticalAlign: "middle"})), w && (c = C(c, {y: v[c.verticalAlign]}))) : x ? c = C(c, {verticalAlign: "top"}) : w && (c = C(c, {y: v[c.verticalAlign]}))); + j ? j.translate(l, m) : j = a.dataLabelsGroup = p.g("data-labels").attr({visibility: a.visible ? "visible" : "hidden", zIndex: 6}).translate(l, m).add(); + h = c; + n(f, function (f) { + K = f.dataLabel; + c = h; + (g = f.options) && g.dataLabels && (c = C(c, g.dataLabels)); + if (z = c.enabled) { + var l = f.barX && f.barX + f.barW / 2 || o(f.plotX, -999), m = o(f.plotY, -999), n = c.y === null ? f.y >= b.threshold ? -H + J : J : c.y; + d = (q ? k.plotWidth - m : l) + c.x; + e = t((q ? k.plotHeight - l : m) + n) + } + if (K && a.isCartesian && (!k.isInsidePlot(d, e) || !z))f.dataLabel = K.destroy(); else if (z) { + var l = c.align, v; + i = c.formatter.call(f.getLabelConfig(), c); + u === "column" && (d += {left: -1, right: 1}[l] * f.barW / 2 || 0); + !r && q && f.y < 0 && (l = "right", d -= 10); + c.style.color = o(c.color, c.style.color, a.color, "black"); + if (K)K.attr({text: i}).animate({x: d, y: e}); else if (s(i)) { + l = + {align: l, fill: c.backgroundColor, stroke: c.borderColor, "stroke-width": c.borderWidth, r: c.borderRadius || 0, rotation: c.rotation, padding: c.padding, zIndex: 1}; + for (v in l)l[v] === A && delete l[v]; + K = f.dataLabel = p[c.rotation ? "text" : "label"](i, d, e, null, null, null, c.useHTML, !0).attr(l).css(c.style).add(j).shadow(c.shadow) + } + if (y && b.stacking && K)v = f.barX, l = f.barY, m = f.barW, f = f.barH, K.align(c, null, {x: q ? k.plotWidth - l - f : v, y: q ? k.plotHeight - v - m : l, width: q ? f : m, height: q ? m : f}) + } + }) + } + }, getSegmentPath: function (a) { + var b = this, c = []; + n(a, + function (d, e) { + b.getPointSpline ? c.push.apply(c, b.getPointSpline(a, d, e)) : (c.push(e ? "L" : "M"), e && b.options.step && c.push(d.plotX, a[e - 1].plotY), c.push(d.plotX, d.plotY)) + }); + return c + }, drawGraph: function () { + var a = this, b = a.options, c = a.graph, d = [], e = a.group, f = b.lineColor || a.color, g = b.lineWidth, h = b.dashStyle, i, j = a.chart.renderer, k = []; + n(a.segments, function (b) { + i = a.getSegmentPath(b); + b.length > 1 ? d = d.concat(i) : k.push(b[0]) + }); + a.graphPath = d; + a.singlePoints = k; + if (c)Fa(c), c.animate({d: d}); else if (g) { + c = {stroke: f, "stroke-width": g}; + if (h)c.dashstyle = h; + a.graph = j.path(d).attr(c).add(e).shadow(b.shadow) + } + }, invertGroups: function () { + function a() { + var a = {width: b.yAxis.len, height: b.xAxis.len}; + c.attr(a).invert(); + d && d.attr(a).invert() + } + + var b = this, c = b.group, d = b.trackerGroup, e = b.chart; + I(e, "resize", a); + I(b, "destroy", function () { + P(e, "resize", a) + }); + a(); + b.invertGroups = a + }, createGroup: function () { + var a = this.chart; + (this.group = a.renderer.g("series")).attr({visibility: this.visible ? "visible" : "hidden", zIndex: this.options.zIndex}).translate(this.xAxis.left, + this.yAxis.top).add(a.seriesGroup); + this.createGroup = Sb + }, render: function () { + var a = this, b = a.chart, c, d = a.options, e = d.clip !== !1, f = d.animation, f = (d = f && a.animate) ? f && f.duration || 500 : 0, g = a.clipRect, h = b.renderer; + if (!g && (g = a.clipRect = !b.hasRendered && b.clipRect ? b.clipRect : h.clipRect(0, 0, b.plotSizeX, b.plotSizeY + 1), !b.clipRect))b.clipRect = g; + a.createGroup(); + c = a.group; + a.drawDataLabels(); + d && a.animate(!0); + a.getAttribs(); + a.drawGraph && a.drawGraph(); + a.drawPoints(); + a.options.enableMouseTracking !== !1 && a.drawTracker(); + b.inverted && a.invertGroups(); + e && !a.hasRendered && (c.clip(g), a.trackerGroup && a.trackerGroup.clip(b.clipRect)); + d && a.animate(); + setTimeout(function () { + g.isAnimating = !1; + if ((c = a.group) && g !== b.clipRect && g.renderer) { + if (e)c.clip(a.clipRect = b.clipRect); + g.destroy() + } + }, f); + a.isDirty = a.isDirtyData = !1; + a.hasRendered = !0 + }, redraw: function () { + var a = this.chart, b = this.isDirtyData, c = this.group; + c && (a.inverted && c.attr({width: a.plotWidth, height: a.plotHeight}), c.animate({translateX: this.xAxis.left, translateY: this.yAxis.top})); + this.translate(); + this.setTooltipPoints(!0); + this.render(); + b && E(this, "updatedData") + }, setState: function (a) { + var b = this.options, c = this.graph, d = b.states, b = b.lineWidth, a = a || ""; + if (this.state !== a)this.state = a, d[a] && d[a].enabled === !1 || (a && (b = d[a].lineWidth || b + 1), c && !c.dashstyle && c.attr({"stroke-width": b}, a ? 0 : 500)) + }, setVisible: function (a, b) { + var c = this.chart, d = this.legendItem, e = this.group, f = this.tracker, g = this.dataLabelsGroup, h, i = this.points, j = c.options.chart.ignoreHiddenSeries; + h = this.visible; + h = (this.visible = + a = a === A ? !h : a) ? "show" : "hide"; + if (e)e[h](); + if (f)f[h](); else if (i)for (e = i.length; e--;)if (f = i[e], f.tracker)f.tracker[h](); + if (g)g[h](); + d && c.legend.colorizeItem(this, a); + this.isDirty = !0; + this.options.stacking && n(c.series, function (a) { + if (a.options.stacking && a.visible)a.isDirty = !0 + }); + if (j)c.isDirtyBox = !0; + b !== !1 && c.redraw(); + E(this, h) + }, show: function () { + this.setVisible(!0) + }, hide: function () { + this.setVisible(!1) + }, select: function (a) { + this.selected = a = a === A ? !this.selected : a; + if (this.checkbox)this.checkbox.checked = a; + E(this, + a ? "select" : "unselect") + }, drawTrackerGroup: function () { + var a = this.trackerGroup, b = this.chart; + if (this.isCartesian) { + if (!a)this.trackerGroup = a = b.renderer.g().attr({zIndex: this.options.zIndex || 1}).add(b.trackerGroup); + a.translate(this.xAxis.left, this.yAxis.top) + } + return a + }, drawTracker: function () { + var a = this, b = a.options, c = b.trackByArea, d = [].concat(c ? a.areaPath : a.graphPath), e = d.length, f = a.chart, g = f.renderer, h = f.options.tooltip.snap, i = a.tracker, j = b.cursor, j = j && {cursor: j}, k = a.singlePoints, l = a.drawTrackerGroup(), + m; + if (e && !c)for (m = e + 1; m--;)d[m] === "M" && d.splice(m + 1, 0, d[m + 1] - h, d[m + 2], "L"), (m && d[m] === "M" || m === e) && d.splice(m, 0, "L", d[m - 2] + h, d[m - 1]); + for (m = 0; m < k.length; m++)e = k[m], d.push("M", e.plotX - h, e.plotY, "L", e.plotX + h, e.plotY); + i ? i.attr({d: d}) : a.tracker = g.path(d).attr({isTracker: !0, "stroke-linejoin": "bevel", visibility: a.visible ? "visible" : "hidden", stroke: tb, fill: c ? tb : U, "stroke-width": b.lineWidth + (c ? 0 : 2 * h)}).on(ea ? "touchstart" : "mouseover",function () { + if (f.hoverSeries !== a)a.onMouseOver() + }).on("mouseout",function () { + if (!b.stickyTracking)a.onMouseOut() + }).css(j).add(l) + }}; + G = ca(R); + Y.line = G; + Z.area = C(T, {threshold: 0}); + G = ca(R, {type: "area", getSegmentPath: function (a) { + var b = R.prototype.getSegmentPath.call(this, a), c = [].concat(b), d, e = this.options; + d = b.length; + var f = this.yAxis.getThreshold(e.threshold); + d === 3 && c.push("L", b[1], b[2]); + if (e.stacking && this.type !== "areaspline")for (d = a.length - 1; d >= 0; d--)d < a.length - 1 && e.step && c.push(a[d + 1].plotX, a[d].yBottom), c.push(a[d].plotX, a[d].yBottom); else c.push("L", a[a.length - 1].plotX, f, "L", a[0].plotX, f); + this.areaPath = this.areaPath.concat(c); + return b + }, + drawGraph: function () { + this.areaPath = []; + R.prototype.drawGraph.apply(this); + var a = this.areaPath, b = this.options, c = this.area; + c ? c.animate({d: a}) : this.area = this.chart.renderer.path(a).attr({fill: o(b.fillColor, pa(this.color).setOpacity(b.fillOpacity || 0.75).get())}).add(this.group) + }, drawLegendSymbol: function (a, b) { + b.legendSymbol = this.chart.renderer.rect(0, a.baseline - 11, a.options.symbolWidth, 12, 2).attr({zIndex: 3}).add(b.legendGroup) + }}); + Y.area = G; + Z.spline = C(T); + ha = ca(R, {type: "spline", getPointSpline: function (a, b, c) { + var d = b.plotX, e = b.plotY, f = a[c - 1], g = a[c + 1], h, i, j, k; + if (c && c < a.length - 1) { + a = f.plotY; + j = g.plotX; + var g = g.plotY, l; + h = (1.5 * d + f.plotX) / 2.5; + i = (1.5 * e + a) / 2.5; + j = (1.5 * d + j) / 2.5; + k = (1.5 * e + g) / 2.5; + l = (k - i) * (j - d) / (j - h) + e - k; + i += l; + k += l; + i > a && i > e ? (i = x(a, e), k = 2 * e - i) : i < a && i < e && (i = O(a, e), k = 2 * e - i); + k > g && k > e ? (k = x(g, e), i = 2 * e - k) : k < g && k < e && (k = O(g, e), i = 2 * e - k); + b.rightContX = j; + b.rightContY = k + } + c ? (b = ["C", f.rightContX || f.plotX, f.rightContY || f.plotY, h || d, i || e, d, e], f.rightContX = f.rightContY = null) : b = ["M", d, e]; + return b + }}); + Y.spline = ha; + Z.areaspline = + C(Z.area); + var Ia = G.prototype, ha = ca(ha, {type: "areaspline", getSegmentPath: Ia.getSegmentPath, drawGraph: Ia.drawGraph}); + Y.areaspline = ha; + Z.column = C(T, {borderColor: "#FFFFFF", borderWidth: 1, borderRadius: 0, groupPadding: 0.2, marker: null, pointPadding: 0.1, minPointLength: 0, cropThreshold: 50, pointRange: null, states: {hover: {brightness: 0.1, shadow: !1}, select: {color: "#C0C0C0", borderColor: "#000000", shadow: !1}}, dataLabels: {y: null, verticalAlign: null}, threshold: 0}); + ha = ca(R, {type: "column", tooltipOutsidePlot: !0, pointAttrToOptions: {stroke: "borderColor", + "stroke-width": "borderWidth", fill: "color", r: "borderRadius"}, init: function () { + R.prototype.init.apply(this, arguments); + var a = this, b = a.chart; + b.hasRendered && n(b.series, function (b) { + if (b.type === a.type)b.isDirty = !0 + }) + }, translate: function () { + var a = this, b = a.chart, c = a.options, d = c.stacking, e = c.borderWidth, f = 0, g = a.xAxis, h = g.reversed, i = {}, j, k; + R.prototype.translate.apply(a); + n(b.series, function (b) { + if (b.type === a.type && b.visible && a.options.group === b.options.group)b.options.stacking ? (j = b.stackKey, i[j] === A && (i[j] = f++), + k = i[j]) : k = f++, b.columnIndex = k + }); + var l = a.points, g = M(g.transA) * (g.ordinalSlope || c.pointRange || g.closestPointRange || 1), m = g * c.groupPadding, p = (g - 2 * m) / f, q = c.pointWidth, t = s(q) ? (p - q) / 2 : p * c.pointPadding, r = o(q, p - 2 * t), y = wa(x(r, 1 + 2 * e)), w = t + (m + ((h ? f - a.columnIndex : a.columnIndex) || 0) * p - g / 2) * (h ? -1 : 1), z = a.yAxis.getThreshold(c.threshold), v = o(c.minPointLength, 5); + n(l, function (c) { + var f = c.plotY, g = o(c.yBottom, z), h = c.plotX + w, i = wa(O(f, g)), j = wa(x(f, g) - i), k = a.yAxis.stacks[(c.y < 0 ? "-" : "") + a.stackKey]; + d && a.visible && k && k[c.x] && + k[c.x].setOffset(w, y); + M(j) < v && v && (j = v, i = M(i - z) > v ? g - v : z - (f <= z ? v : 0)); + u(c, {barX: h, barY: i, barW: y, barH: j, pointWidth: r}); + c.shapeType = "rect"; + c.shapeArgs = f = b.renderer.Element.prototype.crisp.call(0, e, h, i, y, j); + e % 2 && (f.y -= 1, f.height += 1); + c.trackerArgs = M(j) < 3 && C(c.shapeArgs, {height: 6, y: i - 3}) + }) + }, getSymbol: function () { + }, drawLegendSymbol: G.prototype.drawLegendSymbol, drawGraph: function () { + }, drawPoints: function () { + var a = this, b = a.options, c = a.chart.renderer, d, e; + n(a.points, function (f) { + var g = f.plotY; + if (g !== A && !isNaN(g) && + f.y !== null)d = f.graphic, e = f.shapeArgs, d ? (Fa(d), d.animate(C(e))) : f.graphic = d = c[f.shapeType](e).attr(f.pointAttr[f.selected ? "select" : ""]).add(a.group).shadow(b.shadow, null, b.stacking && !b.borderRadius) + }) + }, drawTracker: function () { + var a = this, b = a.chart, c = b.renderer, d, e, f = +new Date, g = a.options, h = g.cursor, i = h && {cursor: h}, j = a.drawTrackerGroup(), k, l, m; + n(a.points, function (h) { + e = h.tracker; + d = h.trackerArgs || h.shapeArgs; + l = h.plotY; + m = !a.isCartesian || l !== A && !isNaN(l); + delete d.strokeWidth; + if (h.y !== null && m)e ? e.attr(d) : + h.tracker = c[h.shapeType](d).attr({isTracker: f, fill: tb, visibility: a.visible ? "visible" : "hidden"}).on(ea ? "touchstart" : "mouseover",function (c) { + k = c.relatedTarget || c.fromElement; + if (b.hoverSeries !== a && z(k, "isTracker") !== f)a.onMouseOver(); + h.onMouseOver() + }).on("mouseout",function (b) { + if (!g.stickyTracking && (k = b.relatedTarget || b.toElement, z(k, "isTracker") !== f))a.onMouseOut() + }).css(i).add(h.group || j) + }) + }, animate: function (a) { + var b = this, c = b.points, d = b.options; + if (!a)n(c, function (a) { + var c = a.graphic, a = a.shapeArgs, g = + b.yAxis, h = d.threshold; + c && (c.attr({height: 0, y: s(h) ? g.getThreshold(h) : g.translate(g.getExtremes().min, 0, 1, 0, 1)}), c.animate({height: a.height, y: a.y}, d.animation)) + }), b.animate = null + }, remove: function () { + var a = this, b = a.chart; + b.hasRendered && n(b.series, function (b) { + if (b.type === a.type)b.isDirty = !0 + }); + R.prototype.remove.apply(a, arguments) + }}); + Y.column = ha; + Z.bar = C(Z.column, {dataLabels: {align: "left", x: 5, y: null, verticalAlign: "middle"}}); + Ia = ca(ha, {type: "bar", inverted: !0}); + Y.bar = Ia; + Z.scatter = C(T, {lineWidth: 0, states: {hover: {lineWidth: 0}}, + tooltip: {headerFormat: '{series.name}
        ', pointFormat: "x: {point.x}
        y: {point.y}
        "}}); + Ia = ca(R, {type: "scatter", sorted: !1, translate: function () { + var a = this; + R.prototype.translate.apply(a); + n(a.points, function (b) { + b.shapeType = "circle"; + b.shapeArgs = {x: b.plotX, y: b.plotY, r: a.chart.options.tooltip.snap} + }) + }, drawTracker: function () { + for (var a = this, b = a.options.cursor, b = b && {cursor: b}, c = a.points, d = c.length, e; d--;)if (e = c[d].graphic)e.element._i = + d; + a._hasTracking ? a._hasTracking = !0 : a.group.attr({isTracker: !0}).on(ea ? "touchstart" : "mouseover",function (b) { + a.onMouseOver(); + if (b.target._i !== A)c[b.target._i].onMouseOver() + }).on("mouseout",function () { + if (!a.options.stickyTracking)a.onMouseOut() + }).css(b) + }}); + Y.scatter = Ia; + Z.pie = C(T, {borderColor: "#FFFFFF", borderWidth: 1, center: ["50%", "50%"], colorByPoint: !0, dataLabels: {distance: 30, enabled: !0, formatter: function () { + return this.point.name + }, y: 5}, legendType: "point", marker: null, size: "75%", showInLegend: !1, slicedOffset: 10, + states: {hover: {brightness: 0.1, shadow: !1}}}); + T = {type: "pie", isCartesian: !1, pointClass: ca(Wa, {init: function () { + Wa.prototype.init.apply(this, arguments); + var a = this, b; + u(a, {visible: a.visible !== !1, name: o(a.name, "Slice")}); + b = function () { + a.slice() + }; + I(a, "select", b); + I(a, "unselect", b); + return a + }, setVisible: function (a) { + var b = this.series.chart, c = this.tracker, d = this.dataLabel, e = this.connector, f = this.shadowGroup, g; + g = (this.visible = a = a === A ? !this.visible : a) ? "show" : "hide"; + this.group[g](); + if (c)c[g](); + if (d)d[g](); + if (e)e[g](); + if (f)f[g](); + this.legendItem && b.legend.colorizeItem(this, a) + }, slice: function (a, b, c) { + var d = this.series.chart, e = this.slicedTranslation; + ua(c, d); + o(b, !0); + a = this.sliced = s(a) ? a : !this.sliced; + a = {translateX: a ? e[0] : d.plotLeft, translateY: a ? e[1] : d.plotTop}; + this.group.animate(a); + this.shadowGroup && this.shadowGroup.animate(a) + }}), pointAttrToOptions: {stroke: "borderColor", "stroke-width": "borderWidth", fill: "color"}, getColor: function () { + this.initialColor = this.chart.counters.color + }, animate: function () { + var a = this; + n(a.points, + function (b) { + var c = b.graphic, b = b.shapeArgs, d = -xa / 2; + c && (c.attr({r: 0, start: d, end: d}), c.animate({r: b.r, start: b.start, end: b.end}, a.options.animation)) + }); + a.animate = null + }, setData: function (a, b) { + R.prototype.setData.call(this, a, !1); + this.processData(); + this.generatePoints(); + o(b, !0) && this.chart.redraw() + }, getCenter: function () { + var a = this.options, b = this.chart, c = b.plotWidth, d = b.plotHeight, a = a.center.concat([a.size, a.innerSize || 0]), e = O(c, d), f; + return Ea(a, function (a, b) { + return(f = /%$/.test(a)) ? [c, d, e, e][b] * w(a) / 100 : a + }) + }, + translate: function () { + this.generatePoints(); + var a = 0, b = -0.25, c = this.options, d = c.slicedOffset, e = d + c.borderWidth, f, g = this.chart, h, i, j, k = this.points, l = 2 * xa, m, p, o, s = c.dataLabels.distance; + this.center = f = this.getCenter(); + this.getX = function (a, b) { + j = L.asin((a - f[1]) / (f[2] / 2 + s)); + return f[0] + (b ? -1 : 1) * X(j) * (f[2] / 2 + s) + }; + n(k, function (b) { + a += b.y + }); + n(k, function (c) { + m = a ? c.y / a : 0; + h = t(b * l * 1E3) / 1E3; + b += m; + i = t(b * l * 1E3) / 1E3; + c.shapeType = "arc"; + c.shapeArgs = {x: f[0], y: f[1], r: f[2] / 2, innerR: f[3] / 2, start: h, end: i}; + j = (i + h) / 2; + c.slicedTranslation = + Ea([X(j) * d + g.plotLeft, da(j) * d + g.plotTop], t); + p = X(j) * f[2] / 2; + o = da(j) * f[2] / 2; + c.tooltipPos = [f[0] + p * 0.7, f[1] + o * 0.7]; + c.labelPos = [f[0] + p + X(j) * s, f[1] + o + da(j) * s, f[0] + p + X(j) * e, f[1] + o + da(j) * e, f[0] + p, f[1] + o, s < 0 ? "center" : j < l / 4 ? "left" : "right", j]; + c.percentage = m * 100; + c.total = a + }); + this.setTooltipPoints() + }, render: function () { + this.getAttribs(); + this.drawPoints(); + this.options.enableMouseTracking !== !1 && this.drawTracker(); + this.drawDataLabels(); + this.options.animation && this.animate && this.animate(); + this.isDirty = !1 + }, drawPoints: function () { + var a = + this, b = a.chart, c = b.renderer, d, e, f, g = a.options.shadow, h, i; + n(a.points, function (j) { + e = j.graphic; + i = j.shapeArgs; + f = j.group; + h = j.shadowGroup; + if (g && !h)h = j.shadowGroup = c.g("shadow").attr({zIndex: 4}).add(); + if (!f)f = j.group = c.g("point").attr({zIndex: 5}).add(); + d = j.sliced ? j.slicedTranslation : [b.plotLeft, b.plotTop]; + f.translate(d[0], d[1]); + h && h.translate(d[0], d[1]); + e ? e.animate(i) : j.graphic = e = c.arc(i).setRadialReference(a.center).attr(u(j.pointAttr[""], {"stroke-linejoin": "round"})).add(j.group).shadow(g, h); + j.visible === !1 && j.setVisible(!1) + }) + }, drawDataLabels: function () { + var a = this.data, b, c = this.chart, d = this.options.dataLabels, e = o(d.connectorPadding, 10), f = o(d.connectorWidth, 1), g, h, i = o(d.softConnector, !0), j = d.distance, k = this.center, l = k[2] / 2, m = k[1], p = j > 0, q = [ + [], + [] + ], s, r, t, u, x = 2, v; + if (d.enabled) { + R.prototype.drawDataLabels.apply(this); + n(a, function (a) { + a.dataLabel && q[a.labelPos[7] < xa / 2 ? 0 : 1].push(a) + }); + q[1].reverse(); + u = function (a, b) { + return b.y - a.y + }; + for (a = q[0][0] && q[0][0].dataLabel && (q[0][0].dataLabel.getBBox().height || 21); x--;) { + var w = + [], C = [], z = q[x], A = z.length, B; + if (j > 0) { + for (v = m - l - j; v <= m + l + j; v += a)w.push(v); + t = w.length; + if (A > t) { + h = [].concat(z); + h.sort(u); + for (v = A; v--;)h[v].rank = v; + for (v = A; v--;)z[v].rank >= t && z.splice(v, 1); + A = z.length + } + for (v = 0; v < A; v++) { + b = z[v]; + h = b.labelPos; + b = 9999; + for (r = 0; r < t; r++)g = M(w[r] - h[1]), g < b && (b = g, B = r); + if (B < v && w[v] !== null)B = v; else for (t < A - v + B && w[v] !== null && (B = t - A + v); w[B] === null;)B++; + C.push({i: B, y: w[B]}); + w[B] = null + } + C.sort(u) + } + for (v = 0; v < A; v++) { + b = z[v]; + h = b.labelPos; + g = b.dataLabel; + t = b.visible === !1 ? "hidden" : "visible"; + s = h[1]; + if (j > + 0) { + if (r = C.pop(), B = r.i, r = r.y, s > r && w[B + 1] !== null || s < r && w[B - 1] !== null)r = s + } else r = s; + s = d.justify ? k[0] + (x ? -1 : 1) * (l + j) : this.getX(B === 0 || B === w.length - 1 ? s : r, x); + g.attr({visibility: t, align: h[6]})[g.moved ? "animate" : "attr"]({x: s + d.x + ({left: e, right: -e}[h[6]] || 0), y: r + d.y}); + g.moved = !0; + if (p && f)g = b.connector, h = i ? ["M", s + (h[6] === "left" ? 5 : -5), r, "C", s, r, 2 * h[2] - h[4], 2 * h[3] - h[5], h[2], h[3], "L", h[4], h[5]] : ["M", s + (h[6] === "left" ? 5 : -5), r, "L", h[2], h[3], "L", h[4], h[5]], g ? (g.animate({d: h}), g.attr("visibility", t)) : b.connector = g = this.chart.renderer.path(h).attr({"stroke-width": f, + stroke: d.connectorColor || b.color || "#606060", visibility: t, zIndex: 3}).translate(c.plotLeft, c.plotTop).add() + } + } + } + }, drawTracker: ha.prototype.drawTracker, drawLegendSymbol: G.prototype.drawLegendSymbol, getSymbol: function () { + }}; + T = ca(R, T); + Y.pie = T; + u(Highcharts, {Axis: ob, CanVGRenderer: fb, Chart: rb, Color: pa, Legend: qb, Point: Wa, Tick: Sa, Tooltip: pb, Renderer: Ta, Series: R, SVGRenderer: qa, VMLRenderer: ka, dateFormat: db, pathAnim: Ua, getOptions: function () { + return V + }, hasBidiBug: Rb, numberFormat: Xa, seriesTypes: Y, setOptions: function (a) { + V = + C(V, a); + Bb(); + return V + }, addEvent: I, removeEvent: P, createElement: S, discardElement: Qa, css: F, each: n, extend: u, map: Ea, merge: C, pick: o, splat: na, extendClass: ca, pInt: w, product: "Highcharts", version: "2.2.5"}) +})(); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts.src.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts.src.js new file mode 100644 index 0000000..2b3de2b --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/highcharts.src.js @@ -0,0 +1,14703 @@ +// ==ClosureCompiler== +// @compilation_level SIMPLE_OPTIMIZATIONS + +/** + * @license Highcharts JS v2.2.5 (2012-06-08) + * + * (c) 2009-2011 Torstein Hønsi + * + * License: www.highcharts.com/license + */ + +// JSLint options: +/*global Highcharts, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */ + +(function () { +// encapsulated variables + var UNDEFINED, + doc = document, + win = window, + math = Math, + mathRound = math.round, + mathFloor = math.floor, + mathCeil = math.ceil, + mathMax = math.max, + mathMin = math.min, + mathAbs = math.abs, + mathCos = math.cos, + mathSin = math.sin, + mathPI = math.PI, + deg2rad = mathPI * 2 / 360, + + + // some variables + userAgent = navigator.userAgent, + isIE = /msie/i.test(userAgent) && !win.opera, + docMode8 = doc.documentMode === 8, + isWebKit = /AppleWebKit/.test(userAgent), + isFirefox = /Firefox/.test(userAgent), + SVG_NS = 'http://www.w3.org/2000/svg', + hasSVG = !!doc.createElementNS && !!doc.createElementNS(SVG_NS, 'svg').createSVGRect, + hasBidiBug = isFirefox && parseInt(userAgent.split('Firefox/')[1], 10) < 4, // issue #38 + useCanVG = !hasSVG && !isIE && !!doc.createElement('canvas').getContext, + Renderer, + hasTouch = doc.documentElement.ontouchstart !== UNDEFINED, + symbolSizes = {}, + idCounter = 0, + garbageBin, + defaultOptions, + dateFormat, // function + globalAnimation, + pathAnim, + timeUnits, + noop = function () { + }, + + // some constants for frequently used strings + DIV = 'div', + ABSOLUTE = 'absolute', + RELATIVE = 'relative', + HIDDEN = 'hidden', + PREFIX = 'highcharts-', + VISIBLE = 'visible', + PX = 'px', + NONE = 'none', + M = 'M', + L = 'L', + /* + * Empirical lowest possible opacities for TRACKER_FILL + * IE6: 0.002 + * IE7: 0.002 + * IE8: 0.002 + * IE9: 0.00000000001 (unlimited) + * FF: 0.00000000001 (unlimited) + * Chrome: 0.000001 + * Safari: 0.000001 + * Opera: 0.00000000001 (unlimited) + */ + TRACKER_FILL = 'rgba(192,192,192,' + (hasSVG ? 0.000001 : 0.002) + ')', // invisible but clickable + //TRACKER_FILL = 'rgba(192,192,192,0.5)', + NORMAL_STATE = '', + HOVER_STATE = 'hover', + SELECT_STATE = 'select', + MILLISECOND = 'millisecond', + SECOND = 'second', + MINUTE = 'minute', + HOUR = 'hour', + DAY = 'day', + WEEK = 'week', + MONTH = 'month', + YEAR = 'year', + + // constants for attributes + FILL = 'fill', + LINEAR_GRADIENT = 'linearGradient', + STOPS = 'stops', + STROKE = 'stroke', + STROKE_WIDTH = 'stroke-width', + + // time methods, changed based on whether or not UTC is used + makeTime, + getMinutes, + getHours, + getDay, + getDate, + getMonth, + getFullYear, + setMinutes, + setHours, + setDate, + setMonth, + setFullYear, + + + // lookup over the types and the associated classes + seriesTypes = {}; + +// The Highcharts namespace + win.Highcharts = {}; + + /** + * Extend an object with the members of another + * @param {Object} a The object to be extended + * @param {Object} b The object to add to the first one + */ + function extend(a, b) { + var n; + if (!a) { + a = {}; + } + for (n in b) { + a[n] = b[n]; + } + return a; + } + + /** + * Take an array and turn into a hash with even number arguments as keys and odd numbers as + * values. Allows creating constants for commonly used style properties, attributes etc. + * Avoid it in performance critical situations like looping + */ + function hash() { + var i = 0, + args = arguments, + length = args.length, + obj = {}; + for (; i < length; i++) { + obj[args[i++]] = args[i]; + } + return obj; + } + + /** + * Shortcut for parseInt + * @param {Object} s + * @param {Number} mag Magnitude + */ + function pInt(s, mag) { + return parseInt(s, mag || 10); + } + + /** + * Check for string + * @param {Object} s + */ + function isString(s) { + return typeof s === 'string'; + } + + /** + * Check for object + * @param {Object} obj + */ + function isObject(obj) { + return typeof obj === 'object'; + } + + /** + * Check for array + * @param {Object} obj + */ + function isArray(obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + } + + /** + * Check for number + * @param {Object} n + */ + function isNumber(n) { + return typeof n === 'number'; + } + + function log2lin(num) { + return math.log(num) / math.LN10; + } + + function lin2log(num) { + return math.pow(10, num); + } + + /** + * Remove last occurence of an item from an array + * @param {Array} arr + * @param {Mixed} item + */ + function erase(arr, item) { + var i = arr.length; + while (i--) { + if (arr[i] === item) { + arr.splice(i, 1); + break; + } + } + //return arr; + } + + /** + * Returns true if the object is not null or undefined. Like MooTools' $.defined. + * @param {Object} obj + */ + function defined(obj) { + return obj !== UNDEFINED && obj !== null; + } + + /** + * Set or get an attribute or an object of attributes. Can't use jQuery attr because + * it attempts to set expando properties on the SVG element, which is not allowed. + * + * @param {Object} elem The DOM element to receive the attribute(s) + * @param {String|Object} prop The property or an abject of key-value pairs + * @param {String} value The value if a single property is set + */ + function attr(elem, prop, value) { + var key, + setAttribute = 'setAttribute', + ret; + + // if the prop is a string + if (isString(prop)) { + // set the value + if (defined(value)) { + + elem[setAttribute](prop, value); + + // get the value + } else if (elem && elem.getAttribute) { // elem not defined when printing pie demo... + ret = elem.getAttribute(prop); + } + + // else if prop is defined, it is a hash of key/value pairs + } else if (defined(prop) && isObject(prop)) { + for (key in prop) { + elem[setAttribute](key, prop[key]); + } + } + return ret; + } + + /** + * Check if an element is an array, and if not, make it into an array. Like + * MooTools' $.splat. + */ + function splat(obj) { + return isArray(obj) ? obj : [obj]; + } + + + /** + * Return the first value that is defined. Like MooTools' $.pick. + */ + function pick() { + var args = arguments, + i, + arg, + length = args.length; + for (i = 0; i < length; i++) { + arg = args[i]; + if (typeof arg !== 'undefined' && arg !== null) { + return arg; + } + } + } + + /** + * Set CSS on a given element + * @param {Object} el + * @param {Object} styles Style object with camel case property names + */ + function css(el, styles) { + if (isIE) { + if (styles && styles.opacity !== UNDEFINED) { + styles.filter = 'alpha(opacity=' + (styles.opacity * 100) + ')'; + } + } + extend(el.style, styles); + } + + /** + * Utility function to create element with attributes and styles + * @param {Object} tag + * @param {Object} attribs + * @param {Object} styles + * @param {Object} parent + * @param {Object} nopad + */ + function createElement(tag, attribs, styles, parent, nopad) { + var el = doc.createElement(tag); + if (attribs) { + extend(el, attribs); + } + if (nopad) { + css(el, {padding: 0, border: NONE, margin: 0}); + } + if (styles) { + css(el, styles); + } + if (parent) { + parent.appendChild(el); + } + return el; + } + + /** + * Extend a prototyped class by new members + * @param {Object} parent + * @param {Object} members + */ + function extendClass(parent, members) { + var object = function () { + }; + object.prototype = new parent(); + extend(object.prototype, members); + return object; + } + + /** + * How many decimals are there in a number + */ + function getDecimals(number) { + + number = (number || 0).toString(); + + return number.indexOf('.') > -1 ? + number.split('.')[1].length : + 0; + } + + /** + * Format a number and return a string based on input settings + * @param {Number} number The input number to format + * @param {Number} decimals The amount of decimals + * @param {String} decPoint The decimal point, defaults to the one given in the lang options + * @param {String} thousandsSep The thousands separator, defaults to the one given in the lang options + */ + function numberFormat(number, decimals, decPoint, thousandsSep) { + var lang = defaultOptions.lang, + // http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_number_format/ + n = number, + c = decimals === -1 ? + getDecimals(number) : + (isNaN(decimals = mathAbs(decimals)) ? 2 : decimals), + d = decPoint === undefined ? lang.decimalPoint : decPoint, + t = thousandsSep === undefined ? lang.thousandsSep : thousandsSep, + s = n < 0 ? "-" : "", + i = String(pInt(n = mathAbs(+n || 0).toFixed(c))), + j = i.length > 3 ? i.length % 3 : 0; + + return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + + (c ? d + mathAbs(n - i).toFixed(c).slice(2) : ""); + } + + /** + * Pad a string to a given length by adding 0 to the beginning + * @param {Number} number + * @param {Number} length + */ + function pad(number, length) { + // Create an array of the remaining length +1 and join it with 0's + return new Array((length || 2) + 1 - String(number).length).join(0) + number; + } + + /** + * Based on http://www.php.net/manual/en/function.strftime.php + * @param {String} format + * @param {Number} timestamp + * @param {Boolean} capitalize + */ + dateFormat = function (format, timestamp, capitalize) { + if (!defined(timestamp) || isNaN(timestamp)) { + return 'Invalid date'; + } + format = pick(format, '%Y-%m-%d %H:%M:%S'); + + var date = new Date(timestamp), + key, // used in for constuct below + // get the basic time values + hours = date[getHours](), + day = date[getDay](), + dayOfMonth = date[getDate](), + month = date[getMonth](), + fullYear = date[getFullYear](), + lang = defaultOptions.lang, + langWeekdays = lang.weekdays, + /* // uncomment this and the 'W' format key below to enable week numbers + weekNumber = function () { + var clone = new Date(date.valueOf()), + day = clone[getDay]() == 0 ? 7 : clone[getDay](), + dayNumber; + clone.setDate(clone[getDate]() + 4 - day); + dayNumber = mathFloor((clone.getTime() - new Date(clone[getFullYear](), 0, 1, -6)) / 86400000); + return 1 + mathFloor(dayNumber / 7); + }, + */ + + // list all format keys + replacements = { + + // Day + 'a': langWeekdays[day].substr(0, 3), // Short weekday, like 'Mon' + 'A': langWeekdays[day], // Long weekday, like 'Monday' + 'd': pad(dayOfMonth), // Two digit day of the month, 01 to 31 + 'e': dayOfMonth, // Day of the month, 1 through 31 + + // Week (none implemented) + //'W': weekNumber(), + + // Month + 'b': lang.shortMonths[month], // Short month, like 'Jan' + 'B': lang.months[month], // Long month, like 'January' + 'm': pad(month + 1), // Two digit month number, 01 through 12 + + // Year + 'y': fullYear.toString().substr(2, 2), // Two digits year, like 09 for 2009 + 'Y': fullYear, // Four digits year, like 2009 + + // Time + 'H': pad(hours), // Two digits hours in 24h format, 00 through 23 + 'I': pad((hours % 12) || 12), // Two digits hours in 12h format, 00 through 11 + 'l': (hours % 12) || 12, // Hours in 12h format, 1 through 12 + 'M': pad(date[getMinutes]()), // Two digits minutes, 00 through 59 + 'p': hours < 12 ? 'AM' : 'PM', // Upper case AM or PM + 'P': hours < 12 ? 'am' : 'pm', // Lower case AM or PM + 'S': pad(date.getSeconds()), // Two digits seconds, 00 through 59 + 'L': pad(mathRound(timestamp % 1000), 3) // Milliseconds (naming from Ruby) + }; + + + // do the replaces + for (key in replacements) { + format = format.replace('%' + key, replacements[key]); + } + + // Optionally capitalize the string and return + return capitalize ? format.substr(0, 1).toUpperCase() + format.substr(1) : format; + }; + + /** + * Take an interval and normalize it to multiples of 1, 2, 2.5 and 5 + * @param {Number} interval + * @param {Array} multiples + * @param {Number} magnitude + * @param {Object} options + */ + function normalizeTickInterval(interval, multiples, magnitude, options) { + var normalized, i; + + // round to a tenfold of 1, 2, 2.5 or 5 + magnitude = pick(magnitude, 1); + normalized = interval / magnitude; + + // multiples for a linear scale + if (!multiples) { + multiples = [1, 2, 2.5, 5, 10]; + + // the allowDecimals option + if (options && options.allowDecimals === false) { + if (magnitude === 1) { + multiples = [1, 2, 5, 10]; + } else if (magnitude <= 0.1) { + multiples = [1 / magnitude]; + } + } + } + + // normalize the interval to the nearest multiple + for (i = 0; i < multiples.length; i++) { + interval = multiples[i]; + if (normalized <= (multiples[i] + (multiples[i + 1] || multiples[i])) / 2) { + break; + } + } + + // multiply back to the correct magnitude + interval *= magnitude; + + return interval; + } + + /** + * Get a normalized tick interval for dates. Returns a configuration object with + * unit range (interval), count and name. Used to prepare data for getTimeTicks. + * Previously this logic was part of getTimeTicks, but as getTimeTicks now runs + * of segments in stock charts, the normalizing logic was extracted in order to + * prevent it for running over again for each segment having the same interval. + * #662, #697. + */ + function normalizeTimeTickInterval(tickInterval, unitsOption) { + var units = unitsOption || [ + [ + MILLISECOND, // unit name + [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + ], + [ + SECOND, + [1, 2, 5, 10, 15, 30] + ], + [ + MINUTE, + [1, 2, 5, 10, 15, 30] + ], + [ + HOUR, + [1, 2, 3, 4, 6, 8, 12] + ], + [ + DAY, + [1, 2] + ], + [ + WEEK, + [1, 2] + ], + [ + MONTH, + [1, 2, 3, 4, 6] + ], + [ + YEAR, + null + ] + ], + unit = units[units.length - 1], // default unit is years + interval = timeUnits[unit[0]], + multiples = unit[1], + count, + i; + + // loop through the units to find the one that best fits the tickInterval + for (i = 0; i < units.length; i++) { + unit = units[i]; + interval = timeUnits[unit[0]]; + multiples = unit[1]; + + + if (units[i + 1]) { + // lessThan is in the middle between the highest multiple and the next unit. + var lessThan = (interval * multiples[multiples.length - 1] + + timeUnits[units[i + 1][0]]) / 2; + + // break and keep the current unit + if (tickInterval <= lessThan) { + break; + } + } + } + + // prevent 2.5 years intervals, though 25, 250 etc. are allowed + if (interval === timeUnits[YEAR] && tickInterval < 5 * interval) { + multiples = [1, 2, 5]; + } + + // prevent 2.5 years intervals, though 25, 250 etc. are allowed + if (interval === timeUnits[YEAR] && tickInterval < 5 * interval) { + multiples = [1, 2, 5]; + } + + // get the count + count = normalizeTickInterval(tickInterval / interval, multiples); + + return { + unitRange: interval, + count: count, + unitName: unit[0] + }; + } + + /** + * Set the tick positions to a time unit that makes sense, for example + * on the first of each month or on every Monday. Return an array + * with the time positions. Used in datetime axes as well as for grouping + * data on a datetime axis. + * + * @param {Object} normalizedInterval The interval in axis values (ms) and the count + * @param {Number} min The minimum in axis values + * @param {Number} max The maximum in axis values + * @param {Number} startOfWeek + */ + function getTimeTicks(normalizedInterval, min, max, startOfWeek) { + var tickPositions = [], + i, + higherRanks = {}, + useUTC = defaultOptions.global.useUTC, + minYear, // used in months and years as a basis for Date.UTC() + minDate = new Date(min), + interval = normalizedInterval.unitRange, + count = normalizedInterval.count; + + + if (interval >= timeUnits[SECOND]) { // second + minDate.setMilliseconds(0); + minDate.setSeconds(interval >= timeUnits[MINUTE] ? 0 : + count * mathFloor(minDate.getSeconds() / count)); + } + + if (interval >= timeUnits[MINUTE]) { // minute + minDate[setMinutes](interval >= timeUnits[HOUR] ? 0 : + count * mathFloor(minDate[getMinutes]() / count)); + } + + if (interval >= timeUnits[HOUR]) { // hour + minDate[setHours](interval >= timeUnits[DAY] ? 0 : + count * mathFloor(minDate[getHours]() / count)); + } + + if (interval >= timeUnits[DAY]) { // day + minDate[setDate](interval >= timeUnits[MONTH] ? 1 : + count * mathFloor(minDate[getDate]() / count)); + } + + if (interval >= timeUnits[MONTH]) { // month + minDate[setMonth](interval >= timeUnits[YEAR] ? 0 : + count * mathFloor(minDate[getMonth]() / count)); + minYear = minDate[getFullYear](); + } + + if (interval >= timeUnits[YEAR]) { // year + minYear -= minYear % count; + minDate[setFullYear](minYear); + } + + // week is a special case that runs outside the hierarchy + if (interval === timeUnits[WEEK]) { + // get start of current week, independent of count + minDate[setDate](minDate[getDate]() - minDate[getDay]() + + pick(startOfWeek, 1)); + } + + + // get tick positions + i = 1; + minYear = minDate[getFullYear](); + var time = minDate.getTime(), + minMonth = minDate[getMonth](), + minDateDate = minDate[getDate](), + timezoneOffset = useUTC ? + 0 : + (24 * 3600 * 1000 + minDate.getTimezoneOffset() * 60 * 1000) % (24 * 3600 * 1000); // #950 + + // iterate and add tick positions at appropriate values + while (time < max) { + tickPositions.push(time); + + // if the interval is years, use Date.UTC to increase years + if (interval === timeUnits[YEAR]) { + time = makeTime(minYear + i * count, 0); + + // if the interval is months, use Date.UTC to increase months + } else if (interval === timeUnits[MONTH]) { + time = makeTime(minYear, minMonth + i * count); + + // if we're using global time, the interval is not fixed as it jumps + // one hour at the DST crossover + } else if (!useUTC && (interval === timeUnits[DAY] || interval === timeUnits[WEEK])) { + time = makeTime(minYear, minMonth, minDateDate + + i * count * (interval === timeUnits[DAY] ? 1 : 7)); + + // else, the interval is fixed and we use simple addition + } else { + time += interval * count; + + // mark new days if the time is dividable by day + if (interval <= timeUnits[HOUR] && time % timeUnits[DAY] === timezoneOffset) { + higherRanks[time] = DAY; + } + } + + i++; + } + + // push the last time + tickPositions.push(time); + + // record information on the chosen unit - for dynamic label formatter + tickPositions.info = extend(normalizedInterval, { + higherRanks: higherRanks, + totalRange: interval * count + }); + + return tickPositions; + } + + /** + * Helper class that contains variuos counters that are local to the chart. + */ + function ChartCounters() { + this.color = 0; + this.symbol = 0; + } + + ChartCounters.prototype = { + /** + * Wraps the color counter if it reaches the specified length. + */ + wrapColor: function (length) { + if (this.color >= length) { + this.color = 0; + } + }, + + /** + * Wraps the symbol counter if it reaches the specified length. + */ + wrapSymbol: function (length) { + if (this.symbol >= length) { + this.symbol = 0; + } + } + }; + + + /** + * Utility method that sorts an object array and keeping the order of equal items. + * ECMA script standard does not specify the behaviour when items are equal. + */ + function stableSort(arr, sortFunction) { + var length = arr.length, + sortValue, + i; + + // Add index to each item + for (i = 0; i < length; i++) { + arr[i].ss_i = i; // stable sort index + } + + arr.sort(function (a, b) { + sortValue = sortFunction(a, b); + return sortValue === 0 ? a.ss_i - b.ss_i : sortValue; + }); + + // Remove index from items + for (i = 0; i < length; i++) { + delete arr[i].ss_i; // stable sort index + } + } + + /** + * Non-recursive method to find the lowest member of an array. Math.min raises a maximum + * call stack size exceeded error in Chrome when trying to apply more than 150.000 points. This + * method is slightly slower, but safe. + */ + function arrayMin(data) { + var i = data.length, + min = data[0]; + + while (i--) { + if (data[i] < min) { + min = data[i]; + } + } + return min; + } + + /** + * Non-recursive method to find the lowest member of an array. Math.min raises a maximum + * call stack size exceeded error in Chrome when trying to apply more than 150.000 points. This + * method is slightly slower, but safe. + */ + function arrayMax(data) { + var i = data.length, + max = data[0]; + + while (i--) { + if (data[i] > max) { + max = data[i]; + } + } + return max; + } + + /** + * Utility method that destroys any SVGElement or VMLElement that are properties on the given object. + * It loops all properties and invokes destroy if there is a destroy method. The property is + * then delete'ed. + * @param {Object} The object to destroy properties on + * @param {Object} Exception, do not destroy this property, only delete it. + */ + function destroyObjectProperties(obj, except) { + var n; + for (n in obj) { + // If the object is non-null and destroy is defined + if (obj[n] && obj[n] !== except && obj[n].destroy) { + // Invoke the destroy + obj[n].destroy(); + } + + // Delete the property from the object. + delete obj[n]; + } + } + + + /** + * Discard an element by moving it to the bin and delete + * @param {Object} The HTML node to discard + */ + function discardElement(element) { + // create a garbage bin element, not part of the DOM + if (!garbageBin) { + garbageBin = createElement(DIV); + } + + // move the node and empty bin + if (element) { + garbageBin.appendChild(element); + } + garbageBin.innerHTML = ''; + } + + /** + * Provide error messages for debugging, with links to online explanation + */ + function error(code, stop) { + var msg = 'Highcharts error #' + code + ': www.highcharts.com/errors/' + code; + if (stop) { + throw msg; + } else if (win.console) { + console.log(msg); + } + } + + /** + * Fix JS round off float errors + * @param {Number} num + */ + function correctFloat(num) { + return parseFloat( + num.toPrecision(14) + ); + } + + /** + * The time unit lookup + */ + /*jslint white: true*/ + timeUnits = hash( + MILLISECOND, 1, + SECOND, 1000, + MINUTE, 60000, + HOUR, 3600000, + DAY, 24 * 3600000, + WEEK, 7 * 24 * 3600000, + MONTH, 30 * 24 * 3600000, + YEAR, 31556952000 + ); + /*jslint white: false*/ + /** + * Path interpolation algorithm used across adapters + */ + pathAnim = { + /** + * Prepare start and end values so that the path can be animated one to one + */ + init: function (elem, fromD, toD) { + fromD = fromD || ''; + var shift = elem.shift, + bezier = fromD.indexOf('C') > -1, + numParams = bezier ? 7 : 3, + endLength, + slice, + i, + start = fromD.split(' '), + end = [].concat(toD), // copy + startBaseLine, + endBaseLine, + sixify = function (arr) { // in splines make move points have six parameters like bezier curves + i = arr.length; + while (i--) { + if (arr[i] === M) { + arr.splice(i + 1, 0, arr[i + 1], arr[i + 2], arr[i + 1], arr[i + 2]); + } + } + }; + + if (bezier) { + sixify(start); + sixify(end); + } + + // pull out the base lines before padding + if (elem.isArea) { + startBaseLine = start.splice(start.length - 6, 6); + endBaseLine = end.splice(end.length - 6, 6); + } + + // if shifting points, prepend a dummy point to the end path + if (shift <= end.length / numParams) { + while (shift--) { + end = [].concat(end).splice(0, numParams).concat(end); + } + } + elem.shift = 0; // reset for following animations + + // copy and append last point until the length matches the end length + if (start.length) { + endLength = end.length; + while (start.length < endLength) { + + //bezier && sixify(start); + slice = [].concat(start).splice(start.length - numParams, numParams); + if (bezier) { // disable first control point + slice[numParams - 6] = slice[numParams - 2]; + slice[numParams - 5] = slice[numParams - 1]; + } + start = start.concat(slice); + } + } + + if (startBaseLine) { // append the base lines for areas + start = start.concat(startBaseLine); + end = end.concat(endBaseLine); + } + return [start, end]; + }, + + /** + * Interpolate each value of the path and return the array + */ + step: function (start, end, pos, complete) { + var ret = [], + i = start.length, + startVal; + + if (pos === 1) { // land on the final path without adjustment points appended in the ends + ret = complete; + + } else if (i === end.length && pos < 1) { + while (i--) { + startVal = parseFloat(start[i]); + ret[i] = + isNaN(startVal) ? // a letter instruction like M or L + start[i] : + pos * (parseFloat(end[i] - startVal)) + startVal; + + } + } else { // if animation is finished or length not matching, land on right value + ret = end; + } + return ret; + } + }; + + + /** + * Set the global animation to either a given value, or fall back to the + * given chart's animation option + * @param {Object} animation + * @param {Object} chart + */ + function setAnimation(animation, chart) { + globalAnimation = pick(animation, chart.animation); + } + + +// check for a custom HighchartsAdapter defined prior to this file + var globalAdapter = win.HighchartsAdapter, + adapter = globalAdapter || {}, + + // Utility functions. If the HighchartsAdapter is not defined, adapter is an empty object + // and all the utility functions will be null. In that case they are populated by the + // default adapters below. + adapterRun = adapter.adapterRun, + getScript = adapter.getScript, + each = adapter.each, + grep = adapter.grep, + offset = adapter.offset, + map = adapter.map, + merge = adapter.merge, + addEvent = adapter.addEvent, + removeEvent = adapter.removeEvent, + fireEvent = adapter.fireEvent, + washMouseEvent = adapter.washMouseEvent, + animate = adapter.animate, + stop = adapter.stop; + + /* + * Define the adapter for frameworks. If an external adapter is not defined, + * Highcharts reverts to the built-in jQuery adapter. + */ + if (globalAdapter && globalAdapter.init) { + // Initialize the adapter with the pathAnim object that takes care + // of path animations. + globalAdapter.init(pathAnim); + } + if (!globalAdapter && win.jQuery) { + var jQ = jQuery; + + /** + * Downloads a script and executes a callback when done. + * @param {String} scriptLocation + * @param {Function} callback + */ + getScript = jQ.getScript; + + /** + * A direct link to jQuery methods. MooTools and Prototype adapters must be implemented for each case of method. + * @param {Object} elem The HTML element + * @param {String} method Which method to run on the wrapped element + */ + adapterRun = function (elem, method) { + return jQ(elem)[method](); + }; + + /** + * Utility for iterating over an array. Parameters are reversed compared to jQuery. + * @param {Array} arr + * @param {Function} fn + */ + each = function (arr, fn) { + var i = 0, + len = arr.length; + for (; i < len; i++) { + if (fn.call(arr[i], arr[i], i, arr) === false) { + return i; + } + } + }; + + /** + * Filter an array + */ + grep = jQ.grep; + + /** + * Map an array + * @param {Array} arr + * @param {Function} fn + */ + map = function (arr, fn) { + //return jQuery.map(arr, fn); + var results = [], + i = 0, + len = arr.length; + for (; i < len; i++) { + results[i] = fn.call(arr[i], arr[i], i, arr); + } + return results; + + }; + + /** + * Deep merge two objects and return a third object + */ + merge = function () { + var args = arguments; + return jQ.extend(true, null, args[0], args[1], args[2], args[3]); + }; + + /** + * Get the position of an element relative to the top left of the page + */ + offset = function (el) { + return jQ(el).offset(); + }; + + /** + * Add an event listener + * @param {Object} el A HTML element or custom object + * @param {String} event The event type + * @param {Function} fn The event handler + */ + addEvent = function (el, event, fn) { + jQ(el).bind(event, fn); + }; + + /** + * Remove event added with addEvent + * @param {Object} el The object + * @param {String} eventType The event type. Leave blank to remove all events. + * @param {Function} handler The function to remove + */ + removeEvent = function (el, eventType, handler) { + // workaround for jQuery issue with unbinding custom events: + // http://forum.jquery.com/topic/javascript-error-when-unbinding-a-custom-event-using-jquery-1-4-2 + var func = doc.removeEventListener ? 'removeEventListener' : 'detachEvent'; + if (doc[func] && !el[func]) { + el[func] = function () { + }; + } + + jQ(el).unbind(eventType, handler); + }; + + /** + * Fire an event on a custom object + * @param {Object} el + * @param {String} type + * @param {Object} eventArguments + * @param {Function} defaultFunction + */ + fireEvent = function (el, type, eventArguments, defaultFunction) { + var event = jQ.Event(type), + detachedType = 'detached' + type, + defaultPrevented; + + // Remove warnings in Chrome when accessing layerX and layerY. Although Highcharts + // never uses these properties, Chrome includes them in the default click event and + // raises the warning when they are copied over in the extend statement below. + // + // To avoid problems in IE (see #1010) where we cannot delete the properties and avoid + // testing if they are there (warning in chrome) the only option is to test if running IE. + if (!isIE && eventArguments) { + delete eventArguments.layerX; + delete eventArguments.layerY; + } + + extend(event, eventArguments); + + // Prevent jQuery from triggering the object method that is named the + // same as the event. For example, if the event is 'select', jQuery + // attempts calling el.select and it goes into a loop. + if (el[type]) { + el[detachedType] = el[type]; + el[type] = null; + } + + // Wrap preventDefault and stopPropagation in try/catch blocks in + // order to prevent JS errors when cancelling events on non-DOM + // objects. #615. + each(['preventDefault', 'stopPropagation'], function (fn) { + var base = event[fn]; + event[fn] = function () { + try { + base.call(event); + } catch (e) { + if (fn === 'preventDefault') { + defaultPrevented = true; + } + } + }; + }); + + // trigger it + jQ(el).trigger(event); + + // attach the method + if (el[detachedType]) { + el[type] = el[detachedType]; + el[detachedType] = null; + } + + if (defaultFunction && !event.isDefaultPrevented() && !defaultPrevented) { + defaultFunction(event); + } + }; + + /** + * Extension method needed for MooTools + */ + washMouseEvent = function (e) { + return e; + }; + + /** + * Animate a HTML element or SVG element wrapper + * @param {Object} el + * @param {Object} params + * @param {Object} options jQuery-like animation options: duration, easing, callback + */ + animate = function (el, params, options) { + var $el = jQ(el); + if (params.d) { + el.toD = params.d; // keep the array form for paths, used in jQ.fx.step.d + params.d = 1; // because in jQuery, animating to an array has a different meaning + } + + $el.stop(); + $el.animate(params, options); + + }; + /** + * Stop running animation + */ + stop = function (el) { + jQ(el).stop(); + }; + + + //=== Extend jQuery on init + + /*jslint unparam: true*/ + /* allow unused param x in this function */ + jQ.extend(jQ.easing, { + easeOutQuad: function (x, t, b, c, d) { + return -c * (t /= d) * (t - 2) + b; + } + }); + /*jslint unparam: false*/ + + // extend the animate function to allow SVG animations + var jFx = jQ.fx, + jStep = jFx.step; + + // extend some methods to check for elem.attr, which means it is a Highcharts SVG object + each(['cur', '_default', 'width', 'height'], function (fn, i) { + var obj = jStep, + base, + elem; + + // Handle different parent objects + if (fn === 'cur') { + obj = jFx.prototype; // 'cur', the getter, relates to jFx.prototype + + } else if (fn === '_default' && jQ.Tween) { // jQuery 1.8 model + obj = jQ.Tween.propHooks[fn]; + fn = 'set'; + } + + // Overwrite the method + base = obj[fn]; + if (base) { // step.width and step.height don't exist in jQuery < 1.7 + + // create the extended function replacement + obj[fn] = function (fx) { + + // jFx.prototype.cur does not use fx argument + fx = i ? fx : this; + + // shortcut + elem = fx.elem; + + // jFX.prototype.cur returns the current value. The other ones are setters + // and returning a value has no effect. + return elem.attr ? // is SVG element wrapper + elem.attr(fx.prop, fn === 'cur' ? UNDEFINED : fx.now) : // apply the SVG wrapper's method + base.apply(this, arguments); // use jQuery's built-in method + }; + } + }); + + // animate paths + jStep.d = function (fx) { + var elem = fx.elem; + + + // Normally start and end should be set in state == 0, but sometimes, + // for reasons unknown, this doesn't happen. Perhaps state == 0 is skipped + // in these cases + if (!fx.started) { + var ends = pathAnim.init(elem, elem.d, elem.toD); + fx.start = ends[0]; + fx.end = ends[1]; + fx.started = true; + } + + + // interpolate each value of the path + elem.attr('d', pathAnim.step(fx.start, fx.end, fx.pos, elem.toD)); + + }; + } + + /* **************************************************************************** + * Handle the options * + *****************************************************************************/ + var + + defaultLabelOptions = { + enabled: true, + // rotation: 0, + align: 'center', + x: 0, + y: 15, + /*formatter: function () { + return this.value; + },*/ + style: { + color: '#666', + fontSize: '11px', + lineHeight: '14px' + } + }; + + defaultOptions = { + colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE', + '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'], + symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], + lang: { + loading: 'Loading...', + months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', + 'August', 'September', 'October', 'November', 'December'], + shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + decimalPoint: '.', + resetZoom: 'Reset zoom', + resetZoomTitle: 'Reset zoom level 1:1', + thousandsSep: ',' + }, + global: { + useUTC: true, + canvasToolsURL: 'http://code.highcharts.com/2.2.5/modules/canvas-tools.js' + }, + chart: { + //animation: true, + //alignTicks: false, + //reflow: true, + //className: null, + //events: { load, selection }, + //margin: [null], + //marginTop: null, + //marginRight: null, + //marginBottom: null, + //marginLeft: null, + borderColor: '#4572A7', + //borderWidth: 0, + borderRadius: 5, + defaultSeriesType: 'line', + ignoreHiddenSeries: true, + //inverted: false, + //shadow: false, + spacingTop: 10, + spacingRight: 10, + spacingBottom: 15, + spacingLeft: 10, + style: { + fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', // default font + fontSize: '12px' + }, + backgroundColor: '#FFFFFF', + //plotBackgroundColor: null, + plotBorderColor: '#C0C0C0', + //plotBorderWidth: 0, + //plotShadow: false, + //zoomType: '' + resetZoomButton: { + theme: { + zIndex: 20 + }, + position: { + align: 'right', + x: -10, + //verticalAlign: 'top', + y: 10 + } + // relativeTo: 'plot' + } + }, + title: { + text: 'Chart title', + align: 'center', + // floating: false, + // margin: 15, + // x: 0, + // verticalAlign: 'top', + y: 15, + style: { + color: '#3E576F', + fontSize: '16px' + } + + }, + subtitle: { + text: '', + align: 'center', + // floating: false + // x: 0, + // verticalAlign: 'top', + y: 30, + style: { + color: '#6D869F' + } + }, + + plotOptions: { + line: { // base series options + allowPointSelect: false, + showCheckbox: false, + animation: { + duration: 1000 + }, + //connectNulls: false, + //cursor: 'default', + //clip: true, + //dashStyle: null, + //enableMouseTracking: true, + events: {}, + //legendIndex: 0, + lineWidth: 2, + shadow: true, + // stacking: null, + marker: { + enabled: true, + //symbol: null, + lineWidth: 0, + radius: 4, + lineColor: '#FFFFFF', + //fillColor: null, + states: { // states for a single point + hover: { + //radius: base + 2 + }, + select: { + fillColor: '#FFFFFF', + lineColor: '#000000', + lineWidth: 2 + } + } + }, + point: { + events: {} + }, + dataLabels: merge(defaultLabelOptions, { + enabled: false, + y: -6, + formatter: function () { + return this.y; + } + // backgroundColor: undefined, + // borderColor: undefined, + // borderRadius: undefined, + // borderWidth: undefined, + // padding: 3, + // shadow: false + }), + cropThreshold: 300, // draw points outside the plot area when the number of points is less than this + pointRange: 0, + //pointStart: 0, + //pointInterval: 1, + showInLegend: true, + states: { // states for the entire series + hover: { + //enabled: false, + //lineWidth: base + 1, + marker: { + // lineWidth: base + 1, + // radius: base + 1 + } + }, + select: { + marker: {} + } + }, + stickyTracking: true + //tooltip: { + //pointFormat: '{series.name}: {point.y}' + //valueDecimals: null, + //xDateFormat: '%A, %b %e, %Y', + //valuePrefix: '', + //ySuffix: '' + //} + // turboThreshold: 1000 + // zIndex: null + } + }, + labels: { + //items: [], + style: { + //font: defaultFont, + position: ABSOLUTE, + color: '#3E576F' + } + }, + legend: { + enabled: true, + align: 'center', + //floating: false, + layout: 'horizontal', + labelFormatter: function () { + return this.name; + }, + borderWidth: 1, + borderColor: '#909090', + borderRadius: 5, + navigation: { + // animation: true, + activeColor: '#3E576F', + // arrowSize: 12 + inactiveColor: '#CCC' + // style: {} // text styles + }, + // margin: 10, + // reversed: false, + shadow: false, + // backgroundColor: null, + /*style: { + padding: '5px' + },*/ + itemStyle: { + cursor: 'pointer', + color: '#3E576F', + fontSize: '12px' + }, + itemHoverStyle: { + //cursor: 'pointer', removed as of #601 + color: '#000' + }, + itemHiddenStyle: { + color: '#CCC' + }, + itemCheckboxStyle: { + position: ABSOLUTE, + width: '13px', // for IE precision + height: '13px' + }, + // itemWidth: undefined, + symbolWidth: 16, + symbolPadding: 5, + verticalAlign: 'bottom', + // width: undefined, + x: 0, + y: 0 + }, + + loading: { + // hideDuration: 100, + labelStyle: { + fontWeight: 'bold', + position: RELATIVE, + top: '1em' + }, + // showDuration: 0, + style: { + position: ABSOLUTE, + backgroundColor: 'white', + opacity: 0.5, + textAlign: 'center' + } + }, + + tooltip: { + enabled: true, + //crosshairs: null, + backgroundColor: 'rgba(255, 255, 255, .85)', + borderWidth: 2, + borderRadius: 5, + dateTimeLabelFormats: { + millisecond: '%A, %b %e, %H:%M:%S.%L', + second: '%A, %b %e, %H:%M:%S', + minute: '%A, %b %e, %H:%M', + hour: '%A, %b %e, %H:%M', + day: '%A, %b %e, %Y', + week: 'Week from %A, %b %e, %Y', + month: '%B %Y', + year: '%Y' + }, + //formatter: defaultFormatter, + headerFormat: '{point.key}
        ', + pointFormat: '{series.name}: {point.y}
        ', + shadow: true, + shared: useCanVG, + snap: hasTouch ? 25 : 10, + style: { + color: '#333333', + fontSize: '12px', + padding: '5px', + whiteSpace: 'nowrap' + } + //xDateFormat: '%A, %b %e, %Y', + //valueDecimals: null, + //valuePrefix: '', + //valueSuffix: '' + }, + + credits: { + enabled: true, + text: 'Highcharts.com', + href: 'http://www.highcharts.com', + position: { + align: 'right', + x: -10, + verticalAlign: 'bottom', + y: -5 + }, + style: { + cursor: 'pointer', + color: '#909090', + fontSize: '10px' + } + } + }; + + +// Series defaults + var defaultPlotOptions = defaultOptions.plotOptions, + defaultSeriesOptions = defaultPlotOptions.line; + +// set the default time methods + setTimeMethods(); + + + /** + * Set the time methods globally based on the useUTC option. Time method can be either + * local time or UTC (default). + */ + function setTimeMethods() { + var useUTC = defaultOptions.global.useUTC, + GET = useUTC ? 'getUTC' : 'get', + SET = useUTC ? 'setUTC' : 'set'; + + makeTime = useUTC ? Date.UTC : function (year, month, date, hours, minutes, seconds) { + return new Date( + year, + month, + pick(date, 1), + pick(hours, 0), + pick(minutes, 0), + pick(seconds, 0) + ).getTime(); + }; + getMinutes = GET + 'Minutes'; + getHours = GET + 'Hours'; + getDay = GET + 'Day'; + getDate = GET + 'Date'; + getMonth = GET + 'Month'; + getFullYear = GET + 'FullYear'; + setMinutes = SET + 'Minutes'; + setHours = SET + 'Hours'; + setDate = SET + 'Date'; + setMonth = SET + 'Month'; + setFullYear = SET + 'FullYear'; + + } + + /** + * Merge the default options with custom options and return the new options structure + * @param {Object} options The new custom options + */ + function setOptions(options) { + + // Pull out axis options and apply them to the respective default axis options + /*defaultXAxisOptions = merge(defaultXAxisOptions, options.xAxis); + defaultYAxisOptions = merge(defaultYAxisOptions, options.yAxis); + options.xAxis = options.yAxis = UNDEFINED;*/ + + // Merge in the default options + defaultOptions = merge(defaultOptions, options); + + // Apply UTC + setTimeMethods(); + + return defaultOptions; + } + + /** + * Get the updated default options. Merely exposing defaultOptions for outside modules + * isn't enough because the setOptions method creates a new object. + */ + function getOptions() { + return defaultOptions; + } + + + /** + * Handle color operations. The object methods are chainable. + * @param {String} input The input color in either rbga or hex format + */ + var Color = function (input) { + // declare variables + var rgba = [], result; + + /** + * Parse the input color to rgba array + * @param {String} input + */ + function init(input) { + + // rgba + result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(input); + if (result) { + rgba = [pInt(result[1]), pInt(result[2]), pInt(result[3]), parseFloat(result[4], 10)]; + } else { // hex + result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(input); + if (result) { + rgba = [pInt(result[1], 16), pInt(result[2], 16), pInt(result[3], 16), 1]; + } + } + + } + + /** + * Return the color a specified format + * @param {String} format + */ + function get(format) { + var ret; + + // it's NaN if gradient colors on a column chart + if (rgba && !isNaN(rgba[0])) { + if (format === 'rgb') { + ret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')'; + } else if (format === 'a') { + ret = rgba[3]; + } else { + ret = 'rgba(' + rgba.join(',') + ')'; + } + } else { + ret = input; + } + return ret; + } + + /** + * Brighten the color + * @param {Number} alpha + */ + function brighten(alpha) { + if (isNumber(alpha) && alpha !== 0) { + var i; + for (i = 0; i < 3; i++) { + rgba[i] += pInt(alpha * 255); + + if (rgba[i] < 0) { + rgba[i] = 0; + } + if (rgba[i] > 255) { + rgba[i] = 255; + } + } + } + return this; + } + + /** + * Set the color's opacity to a given alpha value + * @param {Number} alpha + */ + function setOpacity(alpha) { + rgba[3] = alpha; + return this; + } + + // initialize: parse the input + init(input); + + // public methods + return { + get: get, + brighten: brighten, + setOpacity: setOpacity + }; + }; + + + /** + * A wrapper object for SVG elements + */ + function SVGElement() { + } + + SVGElement.prototype = { + /** + * Initialize the SVG renderer + * @param {Object} renderer + * @param {String} nodeName + */ + init: function (renderer, nodeName) { + var wrapper = this; + wrapper.element = nodeName === 'span' ? + createElement(nodeName) : + doc.createElementNS(SVG_NS, nodeName); + wrapper.renderer = renderer; + /** + * A collection of attribute setters. These methods, if defined, are called right before a certain + * attribute is set on an element wrapper. Returning false prevents the default attribute + * setter to run. Returning a value causes the default setter to set that value. Used in + * Renderer.label. + */ + wrapper.attrSetters = {}; + }, + /** + * Animate a given attribute + * @param {Object} params + * @param {Number} options The same options as in jQuery animation + * @param {Function} complete Function to perform at the end of animation + */ + animate: function (params, options, complete) { + var animOptions = pick(options, globalAnimation, true); + stop(this); // stop regardless of animation actually running, or reverting to .attr (#607) + if (animOptions) { + animOptions = merge(animOptions); + if (complete) { // allows using a callback with the global animation without overwriting it + animOptions.complete = complete; + } + animate(this, params, animOptions); + } else { + this.attr(params); + if (complete) { + complete(); + } + } + }, + /** + * Set or get a given attribute + * @param {Object|String} hash + * @param {Mixed|Undefined} val + */ + attr: function (hash, val) { + var wrapper = this, + key, + value, + result, + i, + child, + element = wrapper.element, + nodeName = element.nodeName, + renderer = wrapper.renderer, + skipAttr, + titleNode, + attrSetters = wrapper.attrSetters, + shadows = wrapper.shadows, + hasSetSymbolSize, + doTransform, + ret = wrapper; + + // single key-value pair + if (isString(hash) && defined(val)) { + key = hash; + hash = {}; + hash[key] = val; + } + + // used as a getter: first argument is a string, second is undefined + if (isString(hash)) { + key = hash; + if (nodeName === 'circle') { + key = { x: 'cx', y: 'cy' }[key] || key; + } else if (key === 'strokeWidth') { + key = 'stroke-width'; + } + ret = attr(element, key) || wrapper[key] || 0; + + if (key !== 'd' && key !== 'visibility') { // 'd' is string in animation step + ret = parseFloat(ret); + } + + // setter + } else { + + for (key in hash) { + skipAttr = false; // reset + value = hash[key]; + + // check for a specific attribute setter + result = attrSetters[key] && attrSetters[key](value, key); + + if (result !== false) { + if (result !== UNDEFINED) { + value = result; // the attribute setter has returned a new value to set + } + + // paths + if (key === 'd') { + if (value && value.join) { // join path + value = value.join(' '); + } + if (/(NaN| {2}|^$)/.test(value)) { + value = 'M 0 0'; + } + //wrapper.d = value; // shortcut for animations + + // update child tspans x values + } else if (key === 'x' && nodeName === 'text') { + for (i = 0; i < element.childNodes.length; i++) { + child = element.childNodes[i]; + // if the x values are equal, the tspan represents a linebreak + if (attr(child, 'x') === attr(element, 'x')) { + //child.setAttribute('x', value); + attr(child, 'x', value); + } + } + + if (wrapper.rotation) { + attr(element, 'transform', 'rotate(' + wrapper.rotation + ' ' + value + ' ' + + pInt(hash.y || attr(element, 'y')) + ')'); + } + + // apply gradients + } else if (key === 'fill') { + value = renderer.color(value, element, key); + + // circle x and y + } else if (nodeName === 'circle' && (key === 'x' || key === 'y')) { + key = { x: 'cx', y: 'cy' }[key] || key; + + // rectangle border radius + } else if (nodeName === 'rect' && key === 'r') { + attr(element, { + rx: value, + ry: value + }); + skipAttr = true; + + // translation and text rotation + } else if (key === 'translateX' || key === 'translateY' || key === 'rotation' || key === 'verticalAlign') { + doTransform = true; + skipAttr = true; + + // apply opacity as subnode (required by legacy WebKit and Batik) + } else if (key === 'stroke') { + value = renderer.color(value, element, key); + + // emulate VML's dashstyle implementation + } else if (key === 'dashstyle') { + key = 'stroke-dasharray'; + value = value && value.toLowerCase(); + if (value === 'solid') { + value = NONE; + } else if (value) { + value = value + .replace('shortdashdotdot', '3,1,1,1,1,1,') + .replace('shortdashdot', '3,1,1,1') + .replace('shortdot', '1,1,') + .replace('shortdash', '3,1,') + .replace('longdash', '8,3,') + .replace(/dot/g, '1,3,') + .replace('dash', '4,3,') + .replace(/,$/, '') + .split(','); // ending comma + + i = value.length; + while (i--) { + value[i] = pInt(value[i]) * hash['stroke-width']; + } + value = value.join(','); + } + + // special + } else if (key === 'isTracker') { + wrapper[key] = value; + + // IE9/MooTools combo: MooTools returns objects instead of numbers and IE9 Beta 2 + // is unable to cast them. Test again with final IE9. + } else if (key === 'width') { + value = pInt(value); + + // Text alignment + } else if (key === 'align') { + key = 'text-anchor'; + value = { left: 'start', center: 'middle', right: 'end' }[value]; + + // Title requires a subnode, #431 + } else if (key === 'title') { + titleNode = element.getElementsByTagName('title')[0]; + if (!titleNode) { + titleNode = doc.createElementNS(SVG_NS, 'title'); + element.appendChild(titleNode); + } + titleNode.textContent = value; + } + + // jQuery animate changes case + if (key === 'strokeWidth') { + key = 'stroke-width'; + } + + // Chrome/Win < 6 bug (http://code.google.com/p/chromium/issues/detail?id=15461) + if (isWebKit && key === 'stroke-width' && value === 0) { + value = 0.000001; + } + + // symbols + if (wrapper.symbolName && /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(key)) { + + + if (!hasSetSymbolSize) { + wrapper.symbolAttr(hash); + hasSetSymbolSize = true; + } + skipAttr = true; + } + + // let the shadow follow the main element + if (shadows && /^(width|height|visibility|x|y|d|transform)$/.test(key)) { + i = shadows.length; + while (i--) { + attr( + shadows[i], + key, + key === 'height' ? + mathMax(value - (shadows[i].cutHeight || 0), 0) : + value + ); + } + } + + // validate heights + if ((key === 'width' || key === 'height') && nodeName === 'rect' && value < 0) { + value = 0; + } + + // Record for animation and quick access without polling the DOM + wrapper[key] = value; + + // Update transform + if (doTransform) { + wrapper.updateTransform(); + } + + + if (key === 'text') { + // only one node allowed + wrapper.textStr = value; + if (wrapper.added) { + renderer.buildText(wrapper); + } + } else if (!skipAttr) { + attr(element, key, value); + } + + } + + } + + } + + // Workaround for our #732, WebKit's issue https://bugs.webkit.org/show_bug.cgi?id=78385 + // TODO: If the WebKit team fix this bug before the final release of Chrome 18, remove the workaround. + if (isWebKit && /Chrome\/(18|19)/.test(userAgent)) { + if (nodeName === 'text' && (hash.x !== UNDEFINED || hash.y !== UNDEFINED)) { + var parent = element.parentNode, + next = element.nextSibling; + + if (parent) { + parent.removeChild(element); + if (next) { + parent.insertBefore(element, next); + } else { + parent.appendChild(element); + } + } + } + } + // End of workaround for #732 + + return ret; + }, + + /** + * If one of the symbol size affecting parameters are changed, + * check all the others only once for each call to an element's + * .attr() method + * @param {Object} hash + */ + symbolAttr: function (hash) { + var wrapper = this; + + each(['x', 'y', 'r', 'start', 'end', 'width', 'height', 'innerR', 'anchorX', 'anchorY'], function (key) { + wrapper[key] = pick(hash[key], wrapper[key]); + }); + + wrapper.attr({ + d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.width, wrapper.height, wrapper) + }); + }, + + /** + * Apply a clipping path to this object + * @param {String} id + */ + clip: function (clipRect) { + return this.attr('clip-path', 'url(' + this.renderer.url + '#' + clipRect.id + ')'); + }, + + /** + * Calculate the coordinates needed for drawing a rectangle crisply and return the + * calculated attributes + * @param {Number} strokeWidth + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + */ + crisp: function (strokeWidth, x, y, width, height) { + + var wrapper = this, + key, + attribs = {}, + values = {}, + normalizer; + + strokeWidth = strokeWidth || wrapper.strokeWidth || (wrapper.attr && wrapper.attr('stroke-width')) || 0; + normalizer = mathRound(strokeWidth) % 2 / 2; // mathRound because strokeWidth can sometimes have roundoff errors + + // normalize for crisp edges + values.x = mathFloor(x || wrapper.x || 0) + normalizer; + values.y = mathFloor(y || wrapper.y || 0) + normalizer; + values.width = mathFloor((width || wrapper.width || 0) - 2 * normalizer); + values.height = mathFloor((height || wrapper.height || 0) - 2 * normalizer); + values.strokeWidth = strokeWidth; + + for (key in values) { + if (wrapper[key] !== values[key]) { // only set attribute if changed + wrapper[key] = attribs[key] = values[key]; + } + } + + return attribs; + }, + + /** + * Set styles for the element + * @param {Object} styles + */ + css: function (styles) { + /*jslint unparam: true*/ + /* allow unused param a in the regexp function below */ + var elemWrapper = this, + elem = elemWrapper.element, + textWidth = styles && styles.width && elem.nodeName === 'text', + n, + serializedCss = '', + hyphenate = function (a, b) { + return '-' + b.toLowerCase(); + }; + /*jslint unparam: false*/ + + // convert legacy + if (styles && styles.color) { + styles.fill = styles.color; + } + + // Merge the new styles with the old ones + styles = extend( + elemWrapper.styles, + styles + ); + + // store object + elemWrapper.styles = styles; + + // serialize and set style attribute + if (isIE && !hasSVG) { // legacy IE doesn't support setting style attribute + if (textWidth) { + delete styles.width; + } + css(elemWrapper.element, styles); + } else { + for (n in styles) { + serializedCss += n.replace(/([A-Z])/g, hyphenate) + ':' + styles[n] + ';'; + } + elemWrapper.attr({ + style: serializedCss + }); + } + + + // re-build text + if (textWidth && elemWrapper.added) { + elemWrapper.renderer.buildText(elemWrapper); + } + + return elemWrapper; + }, + + /** + * Add an event listener + * @param {String} eventType + * @param {Function} handler + */ + on: function (eventType, handler) { + var fn = handler; + // touch + if (hasTouch && eventType === 'click') { + eventType = 'touchstart'; + fn = function (e) { + e.preventDefault(); + handler(); + }; + } + // simplest possible event model for internal use + this.element['on' + eventType] = fn; + return this; + }, + + /** + * Set the coordinates needed to draw a consistent radial gradient across + * pie slices regardless of positioning inside the chart. The format is + * [centerX, centerY, diameter] in pixels. + */ + setRadialReference: function (coordinates) { + this.element.radialReference = coordinates; + return this; + }, + + /** + * Move an object and its children by x and y values + * @param {Number} x + * @param {Number} y + */ + translate: function (x, y) { + return this.attr({ + translateX: x, + translateY: y + }); + }, + + /** + * Invert a group, rotate and flip + */ + invert: function () { + var wrapper = this; + wrapper.inverted = true; + wrapper.updateTransform(); + return wrapper; + }, + + /** + * Apply CSS to HTML elements. This is used in text within SVG rendering and + * by the VML renderer + */ + htmlCss: function (styles) { + var wrapper = this, + element = wrapper.element, + textWidth = styles && element.tagName === 'SPAN' && styles.width; + + if (textWidth) { + delete styles.width; + wrapper.textWidth = textWidth; + wrapper.updateTransform(); + } + + wrapper.styles = extend(wrapper.styles, styles); + css(wrapper.element, styles); + + return wrapper; + }, + + + /** + * VML and useHTML method for calculating the bounding box based on offsets + * @param {Boolean} refresh Whether to force a fresh value from the DOM or to + * use the cached value + * + * @return {Object} A hash containing values for x, y, width and height + */ + + htmlGetBBox: function (refresh) { + var wrapper = this, + element = wrapper.element, + bBox = wrapper.bBox; + + // faking getBBox in exported SVG in legacy IE + if (!bBox || refresh) { + // faking getBBox in exported SVG in legacy IE + if (element.nodeName === 'text') { + element.style.position = ABSOLUTE; + } + + bBox = wrapper.bBox = { + x: element.offsetLeft, + y: element.offsetTop, + width: element.offsetWidth, + height: element.offsetHeight + }; + } + + return bBox; + }, + + /** + * VML override private method to update elements based on internal + * properties based on SVG transform + */ + htmlUpdateTransform: function () { + // aligning non added elements is expensive + if (!this.added) { + this.alignOnAdd = true; + return; + } + + var wrapper = this, + renderer = wrapper.renderer, + elem = wrapper.element, + translateX = wrapper.translateX || 0, + translateY = wrapper.translateY || 0, + x = wrapper.x || 0, + y = wrapper.y || 0, + align = wrapper.textAlign || 'left', + alignCorrection = { left: 0, center: 0.5, right: 1 }[align], + nonLeft = align && align !== 'left', + shadows = wrapper.shadows; + + // apply translate + if (translateX || translateY) { + css(elem, { + marginLeft: translateX, + marginTop: translateY + }); + if (shadows) { // used in labels/tooltip + each(shadows, function (shadow) { + css(shadow, { + marginLeft: translateX + 1, + marginTop: translateY + 1 + }); + }); + } + } + + // apply inversion + if (wrapper.inverted) { // wrapper is a group + each(elem.childNodes, function (child) { + renderer.invertChild(child, elem); + }); + } + + if (elem.tagName === 'SPAN') { + + var width, height, + rotation = wrapper.rotation, + baseline, + radians = 0, + costheta = 1, + sintheta = 0, + quad, + textWidth = pInt(wrapper.textWidth), + xCorr = wrapper.xCorr || 0, + yCorr = wrapper.yCorr || 0, + currentTextTransform = [rotation, align, elem.innerHTML, wrapper.textWidth].join(','); + + if (currentTextTransform !== wrapper.cTT) { // do the calculations and DOM access only if properties changed + + if (defined(rotation)) { + radians = rotation * deg2rad; // deg to rad + costheta = mathCos(radians); + sintheta = mathSin(radians); + + // Adjust for alignment and rotation. Rotation of useHTML content is not yet implemented + // but it can probably be implemented for Firefox 3.5+ on user request. FF3.5+ + // has support for CSS3 transform. The getBBox method also needs to be updated + // to compensate for the rotation, like it currently does for SVG. + // Test case: http://highcharts.com/tests/?file=text-rotation + css(elem, { + filter: rotation ? ['progid:DXImageTransform.Microsoft.Matrix(M11=', costheta, + ', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta, + ', sizingMethod=\'auto expand\')'].join('') : NONE + }); + } + + width = pick(wrapper.elemWidth, elem.offsetWidth); + height = pick(wrapper.elemHeight, elem.offsetHeight); + + // update textWidth + if (width > textWidth && /[ \-]/.test(elem.innerText)) { // #983 + css(elem, { + width: textWidth + PX, + display: 'block', + whiteSpace: 'normal' + }); + width = textWidth; + } + + // correct x and y + baseline = renderer.fontMetrics(elem.style.fontSize).b; + xCorr = costheta < 0 && -width; + yCorr = sintheta < 0 && -height; + + // correct for baseline and corners spilling out after rotation + quad = costheta * sintheta < 0; + xCorr += sintheta * baseline * (quad ? 1 - alignCorrection : alignCorrection); + yCorr -= costheta * baseline * (rotation ? (quad ? alignCorrection : 1 - alignCorrection) : 1); + + // correct for the length/height of the text + if (nonLeft) { + xCorr -= width * alignCorrection * (costheta < 0 ? -1 : 1); + if (rotation) { + yCorr -= height * alignCorrection * (sintheta < 0 ? -1 : 1); + } + css(elem, { + textAlign: align + }); + } + + // record correction + wrapper.xCorr = xCorr; + wrapper.yCorr = yCorr; + } + + // apply position with correction + css(elem, { + left: (x + xCorr) + PX, + top: (y + yCorr) + PX + }); + + // record current text transform + wrapper.cTT = currentTextTransform; + } + }, + + /** + * Private method to update the transform attribute based on internal + * properties + */ + updateTransform: function () { + var wrapper = this, + translateX = wrapper.translateX || 0, + translateY = wrapper.translateY || 0, + inverted = wrapper.inverted, + rotation = wrapper.rotation, + transform = []; + + // flipping affects translate as adjustment for flipping around the group's axis + if (inverted) { + translateX += wrapper.attr('width'); + translateY += wrapper.attr('height'); + } + + // apply translate + if (translateX || translateY) { + transform.push('translate(' + translateX + ',' + translateY + ')'); + } + + // apply rotation + if (inverted) { + transform.push('rotate(90) scale(-1,1)'); + } else if (rotation) { // text rotation + transform.push('rotate(' + rotation + ' ' + (wrapper.x || 0) + ' ' + (wrapper.y || 0) + ')'); + } + + if (transform.length) { + attr(wrapper.element, 'transform', transform.join(' ')); + } + }, + /** + * Bring the element to the front + */ + toFront: function () { + var element = this.element; + element.parentNode.appendChild(element); + return this; + }, + + + /** + * Break down alignment options like align, verticalAlign, x and y + * to x and y relative to the chart. + * + * @param {Object} alignOptions + * @param {Boolean} alignByTranslate + * @param {Object} box The box to align to, needs a width and height + * + */ + align: function (alignOptions, alignByTranslate, box) { + var elemWrapper = this; + + if (!alignOptions) { // called on resize + alignOptions = elemWrapper.alignOptions; + alignByTranslate = elemWrapper.alignByTranslate; + } else { // first call on instanciate + elemWrapper.alignOptions = alignOptions; + elemWrapper.alignByTranslate = alignByTranslate; + if (!box) { // boxes other than renderer handle this internally + elemWrapper.renderer.alignedObjects.push(elemWrapper); + } + } + + box = pick(box, elemWrapper.renderer); + + var align = alignOptions.align, + vAlign = alignOptions.verticalAlign, + x = (box.x || 0) + (alignOptions.x || 0), // default: left align + y = (box.y || 0) + (alignOptions.y || 0), // default: top align + attribs = {}; + + + // align + if (/^(right|center)$/.test(align)) { + x += (box.width - (alignOptions.width || 0)) / + { right: 1, center: 2 }[align]; + } + attribs[alignByTranslate ? 'translateX' : 'x'] = mathRound(x); + + + // vertical align + if (/^(bottom|middle)$/.test(vAlign)) { + y += (box.height - (alignOptions.height || 0)) / + ({ bottom: 1, middle: 2 }[vAlign] || 1); + + } + attribs[alignByTranslate ? 'translateY' : 'y'] = mathRound(y); + + // animate only if already placed + elemWrapper[elemWrapper.placed ? 'animate' : 'attr'](attribs); + elemWrapper.placed = true; + elemWrapper.alignAttr = attribs; + + return elemWrapper; + }, + + /** + * Get the bounding box (width, height, x and y) for the element + */ + getBBox: function (refresh) { + var wrapper = this, + bBox, + width, + height, + rotation = wrapper.rotation, + element = wrapper.element, + rad = rotation * deg2rad; + + // SVG elements + if (element.namespaceURI === SVG_NS || wrapper.renderer.forExport) { + try { // Fails in Firefox if the container has display: none. + + bBox = element.getBBox ? + // SVG: use extend because IE9 is not allowed to change width and height in case + // of rotation (below) + extend({}, element.getBBox()) : + // Canvas renderer and legacy IE in export mode + { + width: element.offsetWidth, + height: element.offsetHeight + }; + } catch (e) { + } + + // If the bBox is not set, the try-catch block above failed. The other condition + // is for Opera that returns a width of -Infinity on hidden elements. + if (!bBox || bBox.width < 0) { + bBox = { width: 0, height: 0 }; + } + + width = bBox.width; + height = bBox.height; + + // adjust for rotated text + if (rotation) { + bBox.width = mathAbs(height * mathSin(rad)) + mathAbs(width * mathCos(rad)); + bBox.height = mathAbs(height * mathCos(rad)) + mathAbs(width * mathSin(rad)); + } + + // VML Renderer or useHTML within SVG + } else { + bBox = wrapper.htmlGetBBox(refresh); + } + + return bBox; + }, + + /** + * Show the element + */ + show: function () { + return this.attr({ visibility: VISIBLE }); + }, + + /** + * Hide the element + */ + hide: function () { + return this.attr({ visibility: HIDDEN }); + }, + + /** + * Add the element + * @param {Object|Undefined} parent Can be an element, an element wrapper or undefined + * to append the element to the renderer.box. + */ + add: function (parent) { + + var renderer = this.renderer, + parentWrapper = parent || renderer, + parentNode = parentWrapper.element || renderer.box, + childNodes = parentNode.childNodes, + element = this.element, + zIndex = attr(element, 'zIndex'), + otherElement, + otherZIndex, + i, + inserted; + + // mark as inverted + this.parentInverted = parent && parent.inverted; + + // build formatted text + if (this.textStr !== undefined) { + renderer.buildText(this); + } + + // mark the container as having z indexed children + if (zIndex) { + parentWrapper.handleZ = true; + zIndex = pInt(zIndex); + } + + // insert according to this and other elements' zIndex + if (parentWrapper.handleZ) { // this element or any of its siblings has a z index + for (i = 0; i < childNodes.length; i++) { + otherElement = childNodes[i]; + otherZIndex = attr(otherElement, 'zIndex'); + if (otherElement !== element && ( + // insert before the first element with a higher zIndex + pInt(otherZIndex) > zIndex || + // if no zIndex given, insert before the first element with a zIndex + (!defined(zIndex) && defined(otherZIndex)) + + )) { + parentNode.insertBefore(element, otherElement); + inserted = true; + break; + } + } + } + + // default: append at the end + if (!inserted) { + parentNode.appendChild(element); + } + + // mark as added + this.added = true; + + // fire an event for internal hooks + fireEvent(this, 'add'); + + return this; + }, + + /** + * Removes a child either by removeChild or move to garbageBin. + * Issue 490; in VML removeChild results in Orphaned nodes according to sIEve, discardElement does not. + */ + safeRemoveChild: function (element) { + var parentNode = element.parentNode; + if (parentNode) { + parentNode.removeChild(element); + } + }, + + /** + * Destroy the element and element wrapper + */ + destroy: function () { + var wrapper = this, + element = wrapper.element || {}, + shadows = wrapper.shadows, + box = wrapper.box, + key, + i; + + // remove events + element.onclick = element.onmouseout = element.onmouseover = element.onmousemove = null; + stop(wrapper); // stop running animations + + if (wrapper.clipPath) { + wrapper.clipPath = wrapper.clipPath.destroy(); + } + + // Destroy stops in case this is a gradient object + if (wrapper.stops) { + for (i = 0; i < wrapper.stops.length; i++) { + wrapper.stops[i] = wrapper.stops[i].destroy(); + } + wrapper.stops = null; + } + + // remove element + wrapper.safeRemoveChild(element); + + // destroy shadows + if (shadows) { + each(shadows, function (shadow) { + wrapper.safeRemoveChild(shadow); + }); + } + + // destroy label box + if (box) { + box.destroy(); + } + + // remove from alignObjects + erase(wrapper.renderer.alignedObjects, wrapper); + + for (key in wrapper) { + delete wrapper[key]; + } + + return null; + }, + + /** + * Empty a group element + */ + empty: function () { + var element = this.element, + childNodes = element.childNodes, + i = childNodes.length; + + while (i--) { + element.removeChild(childNodes[i]); + } + }, + + /** + * Add a shadow to the element. Must be done after the element is added to the DOM + * @param {Boolean} apply + */ + shadow: function (apply, group, cutOff) { + var shadows = [], + i, + shadow, + element = this.element, + strokeWidth, + + // compensate for inverted plot area + transform = this.parentInverted ? '(-1,-1)' : '(1,1)'; + + + if (apply) { + for (i = 1; i <= 3; i++) { + shadow = element.cloneNode(0); + strokeWidth = 7 - 2 * i; + attr(shadow, { + 'isShadow': 'true', + 'stroke': 'rgb(0, 0, 0)', + 'stroke-opacity': 0.05 * i, + 'stroke-width': strokeWidth, + 'transform': 'translate' + transform, + 'fill': NONE + }); + if (cutOff) { + attr(shadow, 'height', mathMax(attr(shadow, 'height') - strokeWidth, 0)); + shadow.cutHeight = strokeWidth; + } + + if (group) { + group.element.appendChild(shadow); + } else { + element.parentNode.insertBefore(shadow, element); + } + + shadows.push(shadow); + } + + this.shadows = shadows; + } + return this; + + } + }; + + + /** + * The default SVG renderer + */ + var SVGRenderer = function () { + this.init.apply(this, arguments); + }; + SVGRenderer.prototype = { + Element: SVGElement, + + /** + * Initialize the SVGRenderer + * @param {Object} container + * @param {Number} width + * @param {Number} height + * @param {Boolean} forExport + */ + init: function (container, width, height, forExport) { + var renderer = this, + loc = location, + boxWrapper; + + boxWrapper = renderer.createElement('svg') + .attr({ + xmlns: SVG_NS, + version: '1.1' + }); + container.appendChild(boxWrapper.element); + + // object properties + renderer.isSVG = true; + renderer.box = boxWrapper.element; + renderer.boxWrapper = boxWrapper; + renderer.alignedObjects = []; + renderer.url = isIE ? '' : loc.href.replace(/#.*?$/, '') + .replace(/([\('\)])/g, '\\$1'); // Page url used for internal references. #24, #672. + renderer.defs = this.createElement('defs').add(); + renderer.forExport = forExport; + renderer.gradients = {}; // Object where gradient SvgElements are stored + + renderer.setSize(width, height, false); + + + // Issue 110 workaround: + // In Firefox, if a div is positioned by percentage, its pixel position may land + // between pixels. The container itself doesn't display this, but an SVG element + // inside this container will be drawn at subpixel precision. In order to draw + // sharp lines, this must be compensated for. This doesn't seem to work inside + // iframes though (like in jsFiddle). + var subPixelFix, rect; + if (isFirefox && container.getBoundingClientRect) { + renderer.subPixelFix = subPixelFix = function () { + css(container, { left: 0, top: 0 }); + rect = container.getBoundingClientRect(); + css(container, { + left: (mathCeil(rect.left) - rect.left) + PX, + top: (mathCeil(rect.top) - rect.top) + PX + }); + }; + + // run the fix now + subPixelFix(); + + // run it on resize + addEvent(win, 'resize', subPixelFix); + } + }, + + /** + * Detect whether the renderer is hidden. This happens when one of the parent elements + * has display: none. #608. + */ + isHidden: function () { + return !this.boxWrapper.getBBox().width; + }, + + /** + * Destroys the renderer and its allocated members. + */ + destroy: function () { + var renderer = this, + rendererDefs = renderer.defs; + renderer.box = null; + renderer.boxWrapper = renderer.boxWrapper.destroy(); + + // Call destroy on all gradient elements + destroyObjectProperties(renderer.gradients || {}); + renderer.gradients = null; + + // Defs are null in VMLRenderer + // Otherwise, destroy them here. + if (rendererDefs) { + renderer.defs = rendererDefs.destroy(); + } + + // Remove sub pixel fix handler + // We need to check that there is a handler, otherwise all functions that are registered for event 'resize' are removed + // See issue #982 + if (renderer.subPixelFix) { + removeEvent(win, 'resize', renderer.subPixelFix); + } + + renderer.alignedObjects = null; + + return null; + }, + + /** + * Create a wrapper for an SVG element + * @param {Object} nodeName + */ + createElement: function (nodeName) { + var wrapper = new this.Element(); + wrapper.init(this, nodeName); + return wrapper; + }, + + /** + * Dummy function for use in canvas renderer + */ + draw: function () { + }, + + /** + * Parse a simple HTML string into SVG tspans + * + * @param {Object} textNode The parent text SVG node + */ + buildText: function (wrapper) { + var textNode = wrapper.element, + lines = pick(wrapper.textStr, '').toString() + .replace(/<(b|strong)>/g, '') + .replace(/<(i|em)>/g, '') + .replace(/
        /g, '
        ') + .split(//g), + childNodes = textNode.childNodes, + styleRegex = /style="([^"]+)"/, + hrefRegex = /href="([^"]+)"/, + parentX = attr(textNode, 'x'), + textStyles = wrapper.styles, + width = textStyles && pInt(textStyles.width), + textLineHeight = textStyles && textStyles.lineHeight, + lastLine, + GET_COMPUTED_STYLE = 'getComputedStyle', + i = childNodes.length, + linePositions = []; + + // Needed in IE9 because it doesn't report tspan's offsetHeight (#893) + function getLineHeightByBBox(lineNo) { + linePositions[lineNo] = textNode.getBBox().height; + return mathRound(linePositions[lineNo] - (linePositions[lineNo - 1] || 0)); + } + + // remove old text + while (i--) { + textNode.removeChild(childNodes[i]); + } + + if (width && !wrapper.added) { + this.box.appendChild(textNode); // attach it to the DOM to read offset width + } + + // remove empty line at end + if (lines[lines.length - 1] === '') { + lines.pop(); + } + + // build the lines + each(lines, function (line, lineNo) { + var spans, spanNo = 0, lineHeight; + + line = line.replace(//g, '|||'); + spans = line.split('|||'); + + each(spans, function (span) { + if (span !== '' || spans.length === 1) { + var attributes = {}, + tspan = doc.createElementNS(SVG_NS, 'tspan'); + if (styleRegex.test(span)) { + attr( + tspan, + 'style', + span.match(styleRegex)[1].replace(/(;| |^)color([ :])/, '$1fill$2') + ); + } + if (hrefRegex.test(span)) { + attr(tspan, 'onclick', 'location.href=\"' + span.match(hrefRegex)[1] + '\"'); + css(tspan, { cursor: 'pointer' }); + } + + span = (span.replace(/<(.|\n)*?>/g, '') || ' ') + .replace(/</g, '<') + .replace(/>/g, '>'); + + // issue #38 workaround. + /*if (reverse) { + arr = []; + i = span.length; + while (i--) { + arr.push(span.charAt(i)); + } + span = arr.join(''); + }*/ + + // add the text node + tspan.appendChild(doc.createTextNode(span)); + + if (!spanNo) { // first span in a line, align it to the left + attributes.x = parentX; + } else { + // Firefox ignores spaces at the front or end of the tspan + attributes.dx = 3; // space + } + + // first span on subsequent line, add the line height + if (!spanNo) { + if (lineNo) { + + // allow getting the right offset height in exporting in IE + if (!hasSVG && wrapper.renderer.forExport) { + css(tspan, { display: 'block' }); + } + + // Webkit and opera sometimes return 'normal' as the line height. In that + // case, webkit uses offsetHeight, while Opera falls back to 18 + lineHeight = win[GET_COMPUTED_STYLE] && + pInt(win[GET_COMPUTED_STYLE](lastLine, null).getPropertyValue('line-height')); + + if (!lineHeight || isNaN(lineHeight)) { + lineHeight = textLineHeight || lastLine.offsetHeight || getLineHeightByBBox(lineNo) || 18; + } + attr(tspan, 'dy', lineHeight); + } + lastLine = tspan; // record for use in next line + } + + // add attributes + attr(tspan, attributes); + + // append it + textNode.appendChild(tspan); + + spanNo++; + + // check width and apply soft breaks + if (width) { + var words = span.replace(/-/g, '- ').split(' '), + tooLong, + actualWidth, + rest = []; + + while (words.length || rest.length) { + actualWidth = wrapper.getBBox().width; + tooLong = actualWidth > width; + if (!tooLong || words.length === 1) { // new line needed + words = rest; + rest = []; + if (words.length) { + tspan = doc.createElementNS(SVG_NS, 'tspan'); + attr(tspan, { + dy: textLineHeight || 16, + x: parentX + }); + textNode.appendChild(tspan); + + if (actualWidth > width) { // a single word is pressing it out + width = actualWidth; + } + } + } else { // append to existing line tspan + tspan.removeChild(tspan.firstChild); + rest.unshift(words.pop()); + } + if (words.length) { + tspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-'))); + } + } + } + } + }); + }); + }, + + /** + * Create a button with preset states + * @param {String} text + * @param {Number} x + * @param {Number} y + * @param {Function} callback + * @param {Object} normalState + * @param {Object} hoverState + * @param {Object} pressedState + */ + button: function (text, x, y, callback, normalState, hoverState, pressedState) { + var label = this.label(text, x, y), + curState = 0, + stateOptions, + stateStyle, + normalStyle, + hoverStyle, + pressedStyle, + STYLE = 'style', + verticalGradient = { x1: 0, y1: 0, x2: 0, y2: 1 }; + + // prepare the attributes + /*jslint white: true*/ + normalState = merge(hash( + STROKE_WIDTH, 1, + STROKE, '#999', + FILL, hash( + LINEAR_GRADIENT, verticalGradient, + STOPS, [ + [0, '#FFF'], + [1, '#DDD'] + ] + ), + 'r', 3, + 'padding', 3, + STYLE, hash( + 'color', 'black' + ) + ), normalState); + /*jslint white: false*/ + normalStyle = normalState[STYLE]; + delete normalState[STYLE]; + + /*jslint white: true*/ + hoverState = merge(normalState, hash( + STROKE, '#68A', + FILL, hash( + LINEAR_GRADIENT, verticalGradient, + STOPS, [ + [0, '#FFF'], + [1, '#ACF'] + ] + ) + ), hoverState); + /*jslint white: false*/ + hoverStyle = hoverState[STYLE]; + delete hoverState[STYLE]; + + /*jslint white: true*/ + pressedState = merge(normalState, hash( + STROKE, '#68A', + FILL, hash( + LINEAR_GRADIENT, verticalGradient, + STOPS, [ + [0, '#9BD'], + [1, '#CDF'] + ] + ) + ), pressedState); + /*jslint white: false*/ + pressedStyle = pressedState[STYLE]; + delete pressedState[STYLE]; + + // add the events + addEvent(label.element, 'mouseenter', function () { + label.attr(hoverState) + .css(hoverStyle); + }); + addEvent(label.element, 'mouseleave', function () { + stateOptions = [normalState, hoverState, pressedState][curState]; + stateStyle = [normalStyle, hoverStyle, pressedStyle][curState]; + label.attr(stateOptions) + .css(stateStyle); + }); + + label.setState = function (state) { + curState = state; + if (!state) { + label.attr(normalState) + .css(normalStyle); + } else if (state === 2) { + label.attr(pressedState) + .css(pressedStyle); + } + }; + + return label + .on('click', function () { + callback.call(label); + }) + .attr(normalState) + .css(extend({ cursor: 'default' }, normalStyle)); + }, + + /** + * Make a straight line crisper by not spilling out to neighbour pixels + * @param {Array} points + * @param {Number} width + */ + crispLine: function (points, width) { + // points format: [M, 0, 0, L, 100, 0] + // normalize to a crisp line + if (points[1] === points[4]) { + points[1] = points[4] = mathRound(points[1]) + (width % 2 / 2); + } + if (points[2] === points[5]) { + points[2] = points[5] = mathRound(points[2]) + (width % 2 / 2); + } + return points; + }, + + + /** + * Draw a path + * @param {Array} path An SVG path in array form + */ + path: function (path) { + var attr = { + fill: NONE + }; + if (isArray(path)) { + attr.d = path; + } else if (isObject(path)) { // attributes + extend(attr, path); + } + return this.createElement('path').attr(attr); + }, + + /** + * Draw and return an SVG circle + * @param {Number} x The x position + * @param {Number} y The y position + * @param {Number} r The radius + */ + circle: function (x, y, r) { + var attr = isObject(x) ? + x : + { + x: x, + y: y, + r: r + }; + + return this.createElement('circle').attr(attr); + }, + + /** + * Draw and return an arc + * @param {Number} x X position + * @param {Number} y Y position + * @param {Number} r Radius + * @param {Number} innerR Inner radius like used in donut charts + * @param {Number} start Starting angle + * @param {Number} end Ending angle + */ + arc: function (x, y, r, innerR, start, end) { + // arcs are defined as symbols for the ability to set + // attributes in attr and animate + + if (isObject(x)) { + y = x.y; + r = x.r; + innerR = x.innerR; + start = x.start; + end = x.end; + x = x.x; + } + return this.symbol('arc', x || 0, y || 0, r || 0, r || 0, { + innerR: innerR || 0, + start: start || 0, + end: end || 0 + }); + }, + + /** + * Draw and return a rectangle + * @param {Number} x Left position + * @param {Number} y Top position + * @param {Number} width + * @param {Number} height + * @param {Number} r Border corner radius + * @param {Number} strokeWidth A stroke width can be supplied to allow crisp drawing + */ + rect: function (x, y, width, height, r, strokeWidth) { + + r = isObject(x) ? x.r : r; + + var wrapper = this.createElement('rect').attr({ + rx: r, + ry: r, + fill: NONE + }); + return wrapper.attr( + isObject(x) ? + x : + // do not crispify when an object is passed in (as in column charts) + wrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0)) + ); + }, + + /** + * Resize the box and re-align all aligned elements + * @param {Object} width + * @param {Object} height + * @param {Boolean} animate + * + */ + setSize: function (width, height, animate) { + var renderer = this, + alignedObjects = renderer.alignedObjects, + i = alignedObjects.length; + + renderer.width = width; + renderer.height = height; + + renderer.boxWrapper[pick(animate, true) ? 'animate' : 'attr']({ + width: width, + height: height + }); + + while (i--) { + alignedObjects[i].align(); + } + }, + + /** + * Create a group + * @param {String} name The group will be given a class name of 'highcharts-{name}'. + * This can be used for styling and scripting. + */ + g: function (name) { + var elem = this.createElement('g'); + return defined(name) ? elem.attr({ 'class': PREFIX + name }) : elem; + }, + + /** + * Display an image + * @param {String} src + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + */ + image: function (src, x, y, width, height) { + var attribs = { + preserveAspectRatio: NONE + }, + elemWrapper; + + // optional properties + if (arguments.length > 1) { + extend(attribs, { + x: x, + y: y, + width: width, + height: height + }); + } + + elemWrapper = this.createElement('image').attr(attribs); + + // set the href in the xlink namespace + if (elemWrapper.element.setAttributeNS) { + elemWrapper.element.setAttributeNS('http://www.w3.org/1999/xlink', + 'href', src); + } else { + // could be exporting in IE + // using href throws "not supported" in ie7 and under, requries regex shim to fix later + elemWrapper.element.setAttribute('hc-svg-href', src); + } + + return elemWrapper; + }, + + /** + * Draw a symbol out of pre-defined shape paths from the namespace 'symbol' object. + * + * @param {Object} symbol + * @param {Object} x + * @param {Object} y + * @param {Object} radius + * @param {Object} options + */ + symbol: function (symbol, x, y, width, height, options) { + + var obj, + + // get the symbol definition function + symbolFn = this.symbols[symbol], + + // check if there's a path defined for this symbol + path = symbolFn && symbolFn( + mathRound(x), + mathRound(y), + width, + height, + options + ), + + imageRegex = /^url\((.*?)\)$/, + imageSrc, + imageSize, + centerImage; + + if (path) { + + obj = this.path(path); + // expando properties for use in animate and attr + extend(obj, { + symbolName: symbol, + x: x, + y: y, + width: width, + height: height + }); + if (options) { + extend(obj, options); + } + + + // image symbols + } else if (imageRegex.test(symbol)) { + + // On image load, set the size and position + centerImage = function (img, size) { + img.attr({ + width: size[0], + height: size[1] + }); + + if (!img.alignByTranslate) { // #185 + img.translate( + -mathRound(size[0] / 2), + -mathRound(size[1] / 2) + ); + } + }; + + imageSrc = symbol.match(imageRegex)[1]; + imageSize = symbolSizes[imageSrc]; + + // create the image synchronously, add attribs async + obj = this.image(imageSrc) + .attr({ + x: x, + y: y + }); + + if (imageSize) { + centerImage(obj, imageSize); + } else { + // initialize image to be 0 size so export will still function if there's no cached sizes + obj.attr({ width: 0, height: 0 }); + + // create a dummy JavaScript image to get the width and height + createElement('img', { + onload: function () { + var img = this; + + centerImage(obj, symbolSizes[imageSrc] = [img.width, img.height]); + }, + src: imageSrc + }); + } + } + + return obj; + }, + + /** + * An extendable collection of functions for defining symbol paths. + */ + symbols: { + 'circle': function (x, y, w, h) { + var cpw = 0.166 * w; + return [ + M, x + w / 2, y, + 'C', x + w + cpw, y, x + w + cpw, y + h, x + w / 2, y + h, + 'C', x - cpw, y + h, x - cpw, y, x + w / 2, y, + 'Z' + ]; + }, + + 'square': function (x, y, w, h) { + return [ + M, x, y, + L, x + w, y, + x + w, y + h, + x, y + h, + 'Z' + ]; + }, + + 'triangle': function (x, y, w, h) { + return [ + M, x + w / 2, y, + L, x + w, y + h, + x, y + h, + 'Z' + ]; + }, + + 'triangle-down': function (x, y, w, h) { + return [ + M, x, y, + L, x + w, y, + x + w / 2, y + h, + 'Z' + ]; + }, + 'diamond': function (x, y, w, h) { + return [ + M, x + w / 2, y, + L, x + w, y + h / 2, + x + w / 2, y + h, + x, y + h / 2, + 'Z' + ]; + }, + 'arc': function (x, y, w, h, options) { + var start = options.start, + radius = options.r || w || h, + end = options.end - 0.000001, // to prevent cos and sin of start and end from becoming equal on 360 arcs + innerRadius = options.innerR, + open = options.open, + cosStart = mathCos(start), + sinStart = mathSin(start), + cosEnd = mathCos(end), + sinEnd = mathSin(end), + longArc = options.end - start < mathPI ? 0 : 1; + + return [ + M, + x + radius * cosStart, + y + radius * sinStart, + 'A', // arcTo + radius, // x radius + radius, // y radius + 0, // slanting + longArc, // long or short arc + 1, // clockwise + x + radius * cosEnd, + y + radius * sinEnd, + open ? M : L, + x + innerRadius * cosEnd, + y + innerRadius * sinEnd, + 'A', // arcTo + innerRadius, // x radius + innerRadius, // y radius + 0, // slanting + longArc, // long or short arc + 0, // clockwise + x + innerRadius * cosStart, + y + innerRadius * sinStart, + + open ? '' : 'Z' // close + ]; + } + }, + + /** + * Define a clipping rectangle + * @param {String} id + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + */ + clipRect: function (x, y, width, height) { + var wrapper, + id = PREFIX + idCounter++, + + clipPath = this.createElement('clipPath').attr({ + id: id + }).add(this.defs); + + wrapper = this.rect(x, y, width, height, 0).add(clipPath); + wrapper.id = id; + wrapper.clipPath = clipPath; + + return wrapper; + }, + + + /** + * Take a color and return it if it's a string, make it a gradient if it's a + * gradient configuration object. Prior to Highstock, an array was used to define + * a linear gradient with pixel positions relative to the SVG. In newer versions + * we change the coordinates to apply relative to the shape, using coordinates + * 0-1 within the shape. To preserve backwards compatibility, linearGradient + * in this definition is an object of x1, y1, x2 and y2. + * + * @param {Object} color The color or config object + */ + color: function (color, elem, prop) { + var renderer = this, + colorObject, + regexRgba = /^rgba/, + gradName; + + // Apply linear or radial gradients + if (color && color.linearGradient) { + gradName = 'linearGradient'; + } else if (color && color.radialGradient) { + gradName = 'radialGradient'; + } + + if (gradName) { + var gradAttr = color[gradName], + gradients = renderer.gradients, + gradientObject, + stopColor, + stopOpacity, + radialReference = elem.radialReference; + + // Check if a gradient object with the same config object is created within this renderer + if (!gradAttr.id || !gradients[gradAttr.id]) { + + // Keep < 2.2 kompatibility + if (isArray(gradAttr)) { + color[gradName] = gradAttr = { + x1: gradAttr[0], + y1: gradAttr[1], + x2: gradAttr[2], + y2: gradAttr[3], + gradientUnits: 'userSpaceOnUse' + }; + } + + // Correct the radial gradient for the radial reference system + if (gradName === 'radialGradient' && radialReference && !defined(gradAttr.gradientUnits)) { + extend(gradAttr, { + cx: (radialReference[0] - radialReference[2] / 2) + gradAttr.cx * radialReference[2], + cy: (radialReference[1] - radialReference[2] / 2) + gradAttr.cy * radialReference[2], + r: gradAttr.r * radialReference[2], + gradientUnits: 'userSpaceOnUse' + }); + } + + // Set the id and create the element + gradAttr.id = PREFIX + idCounter++; + gradients[gradAttr.id] = gradientObject = renderer.createElement(gradName) + .attr(gradAttr) + .add(renderer.defs); + + + // The gradient needs to keep a list of stops to be able to destroy them + gradientObject.stops = []; + each(color.stops, function (stop) { + var stopObject; + if (regexRgba.test(stop[1])) { + colorObject = Color(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } else { + stopColor = stop[1]; + stopOpacity = 1; + } + stopObject = renderer.createElement('stop').attr({ + offset: stop[0], + 'stop-color': stopColor, + 'stop-opacity': stopOpacity + }).add(gradientObject); + + // Add the stop element to the gradient + gradientObject.stops.push(stopObject); + }); + } + + // Return the reference to the gradient object + return 'url(' + renderer.url + '#' + gradAttr.id + ')'; + + // Webkit and Batik can't show rgba. + } else if (regexRgba.test(color)) { + colorObject = Color(color); + attr(elem, prop + '-opacity', colorObject.get('a')); + + return colorObject.get('rgb'); + + + } else { + // Remove the opacity attribute added above. Does not throw if the attribute is not there. + elem.removeAttribute(prop + '-opacity'); + + return color; + } + + }, + + + /** + * Add text to the SVG object + * @param {String} str + * @param {Number} x Left position + * @param {Number} y Top position + * @param {Boolean} useHTML Use HTML to render the text + */ + text: function (str, x, y, useHTML) { + + // declare variables + var renderer = this, + defaultChartStyle = defaultOptions.chart.style, + wrapper; + + if (useHTML && !renderer.forExport) { + return renderer.html(str, x, y); + } + + x = mathRound(pick(x, 0)); + y = mathRound(pick(y, 0)); + + wrapper = renderer.createElement('text') + .attr({ + x: x, + y: y, + text: str + }) + .css({ + fontFamily: defaultChartStyle.fontFamily, + fontSize: defaultChartStyle.fontSize + }); + + wrapper.x = x; + wrapper.y = y; + return wrapper; + }, + + + /** + * Create HTML text node. This is used by the VML renderer as well as the SVG + * renderer through the useHTML option. + * + * @param {String} str + * @param {Number} x + * @param {Number} y + */ + html: function (str, x, y) { + var defaultChartStyle = defaultOptions.chart.style, + wrapper = this.createElement('span'), + attrSetters = wrapper.attrSetters, + element = wrapper.element, + renderer = wrapper.renderer; + + // Text setter + attrSetters.text = function (value) { + element.innerHTML = value; + return false; + }; + + // Various setters which rely on update transform + attrSetters.x = attrSetters.y = attrSetters.align = function (value, key) { + if (key === 'align') { + key = 'textAlign'; // Do not overwrite the SVGElement.align method. Same as VML. + } + wrapper[key] = value; + wrapper.htmlUpdateTransform(); + return false; + }; + + // Set the default attributes + wrapper.attr({ + text: str, + x: mathRound(x), + y: mathRound(y) + }) + .css({ + position: ABSOLUTE, + whiteSpace: 'nowrap', + fontFamily: defaultChartStyle.fontFamily, + fontSize: defaultChartStyle.fontSize + }); + + // Use the HTML specific .css method + wrapper.css = wrapper.htmlCss; + + // This is specific for HTML within SVG + if (renderer.isSVG) { + wrapper.add = function (svgGroupWrapper) { + + var htmlGroup, + htmlGroupStyle, + container = renderer.box.parentNode; + + // Create a mock group to hold the HTML elements + if (svgGroupWrapper) { + htmlGroup = svgGroupWrapper.div; + if (!htmlGroup) { + htmlGroup = svgGroupWrapper.div = createElement(DIV, { + className: attr(svgGroupWrapper.element, 'class') + }, { + position: ABSOLUTE, + left: svgGroupWrapper.attr('translateX') + PX, + top: svgGroupWrapper.attr('translateY') + PX + }, container); + + // Ensure dynamic updating position + htmlGroupStyle = htmlGroup.style; + extend(svgGroupWrapper.attrSetters, { + translateX: function (value) { + htmlGroupStyle.left = value + PX; + }, + translateY: function (value) { + htmlGroupStyle.top = value + PX; + }, + visibility: function (value, key) { + htmlGroupStyle[key] = value; + } + }); + + } + } else { + htmlGroup = container; + } + + htmlGroup.appendChild(element); + + // Shared with VML: + wrapper.added = true; + if (wrapper.alignOnAdd) { + wrapper.htmlUpdateTransform(); + } + + return wrapper; + }; + } + return wrapper; + }, + + /** + * Utility to return the baseline offset and total line height from the font size + */ + fontMetrics: function (fontSize) { + fontSize = pInt(fontSize || 11); + + // Empirical values found by comparing font size and bounding box height. + // Applies to the default font family. http://jsfiddle.net/highcharts/7xvn7/ + var lineHeight = fontSize < 24 ? fontSize + 4 : mathRound(fontSize * 1.2), + baseline = mathRound(lineHeight * 0.8); + + return { + h: lineHeight, + b: baseline + }; + }, + + /** + * Add a label, a text item that can hold a colored or gradient background + * as well as a border and shadow. + * @param {string} str + * @param {Number} x + * @param {Number} y + * @param {String} shape + * @param {Number} anchorX In case the shape has a pointer, like a flag, this is the + * coordinates it should be pinned to + * @param {Number} anchorY + * @param {Boolean} baseline Whether to position the label relative to the text baseline, + * like renderer.text, or to the upper border of the rectangle. + * @param {String} className Class name for the group + */ + label: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) { + + var renderer = this, + wrapper = renderer.g(className), + text = renderer.text('', 0, 0, useHTML) + .attr({ + zIndex: 1 + }) + .add(wrapper), + box, + bBox, + alignFactor = 0, + padding = 3, + width, + height, + wrapperX, + wrapperY, + crispAdjust = 0, + deferredAttr = {}, + baselineOffset, + attrSetters = wrapper.attrSetters; + + /** + * This function runs after the label is added to the DOM (when the bounding box is + * available), and after the text of the label is updated to detect the new bounding + * box and reflect it in the border box. + */ + function updateBoxSize() { + var boxY, + style = text.element.style; + + bBox = (width === undefined || height === undefined || wrapper.styles.textAlign) && + text.getBBox(true); + wrapper.width = (width || bBox.width || 0) + 2 * padding; + wrapper.height = (height || bBox.height || 0) + 2 * padding; + + // update the label-scoped y offset + baselineOffset = padding + renderer.fontMetrics(style && style.fontSize).b; + + + // create the border box if it is not already present + if (!box) { + boxY = baseline ? -baselineOffset : 0; + + wrapper.box = box = shape ? + renderer.symbol(shape, -alignFactor * padding, boxY, wrapper.width, wrapper.height) : + renderer.rect(-alignFactor * padding, boxY, wrapper.width, wrapper.height, 0, deferredAttr[STROKE_WIDTH]); + box.add(wrapper); + } + + // apply the box attributes + box.attr(merge({ + width: wrapper.width, + height: wrapper.height + }, deferredAttr)); + deferredAttr = null; + } + + /** + * This function runs after setting text or padding, but only if padding is changed + */ + function updateTextPadding() { + var styles = wrapper.styles, + textAlign = styles && styles.textAlign, + x = padding * (1 - alignFactor), + y; + + // determin y based on the baseline + y = baseline ? 0 : baselineOffset; + + // compensate for alignment + if (defined(width) && (textAlign === 'center' || textAlign === 'right')) { + x += { center: 0.5, right: 1 }[textAlign] * (width - bBox.width); + } + + // update if anything changed + if (x !== text.x || y !== text.y) { + text.attr({ + x: x, + y: y + }); + } + + // record current values + text.x = x; + text.y = y; + } + + /** + * Set a box attribute, or defer it if the box is not yet created + * @param {Object} key + * @param {Object} value + */ + function boxAttr(key, value) { + if (box) { + box.attr(key, value); + } else { + deferredAttr[key] = value; + } + } + + function getSizeAfterAdd() { + wrapper.attr({ + text: str, // alignment is available now + x: x, + y: y + }); + + if (defined(anchorX)) { + wrapper.attr({ + anchorX: anchorX, + anchorY: anchorY + }); + } + } + + /** + * After the text element is added, get the desired size of the border box + * and add it before the text in the DOM. + */ + addEvent(wrapper, 'add', getSizeAfterAdd); + + /* + * Add specific attribute setters. + */ + + // only change local variables + attrSetters.width = function (value) { + width = value; + return false; + }; + attrSetters.height = function (value) { + height = value; + return false; + }; + attrSetters.padding = function (value) { + if (defined(value) && value !== padding) { + padding = value; + updateTextPadding(); + } + + return false; + }; + + // change local variable and set attribue as well + attrSetters.align = function (value) { + alignFactor = { left: 0, center: 0.5, right: 1 }[value]; + return false; // prevent setting text-anchor on the group + }; + + // apply these to the box and the text alike + attrSetters.text = function (value, key) { + text.attr(key, value); + updateBoxSize(); + updateTextPadding(); + return false; + }; + + // apply these to the box but not to the text + attrSetters[STROKE_WIDTH] = function (value, key) { + crispAdjust = value % 2 / 2; + boxAttr(key, value); + return false; + }; + attrSetters.stroke = attrSetters.fill = attrSetters.r = function (value, key) { + boxAttr(key, value); + return false; + }; + attrSetters.anchorX = function (value, key) { + anchorX = value; + boxAttr(key, value + crispAdjust - wrapperX); + return false; + }; + attrSetters.anchorY = function (value, key) { + anchorY = value; + boxAttr(key, value - wrapperY); + return false; + }; + + // rename attributes + attrSetters.x = function (value) { + wrapper.x = value; // for animation getter + value -= alignFactor * ((width || bBox.width) + padding); + wrapperX = mathRound(value); + + wrapper.attr('translateX', wrapperX); + return false; + }; + attrSetters.y = function (value) { + wrapperY = wrapper.y = mathRound(value); + wrapper.attr('translateY', value); + return false; + }; + + // Redirect certain methods to either the box or the text + var baseCss = wrapper.css; + return extend(wrapper, { + /** + * Pick up some properties and apply them to the text instead of the wrapper + */ + css: function (styles) { + if (styles) { + var textStyles = {}; + styles = merge({}, styles); // create a copy to avoid altering the original object (#537) + each(['fontSize', 'fontWeight', 'fontFamily', 'color', 'lineHeight', 'width'], function (prop) { + if (styles[prop] !== UNDEFINED) { + textStyles[prop] = styles[prop]; + delete styles[prop]; + } + }); + text.css(textStyles); + } + return baseCss.call(wrapper, styles); + }, + /** + * Return the bounding box of the box, not the group + */ + getBBox: function () { + return box.getBBox(); + }, + /** + * Apply the shadow to the box + */ + shadow: function (b) { + box.shadow(b); + return wrapper; + }, + /** + * Destroy and release memory. + */ + destroy: function () { + removeEvent(wrapper, 'add', getSizeAfterAdd); + + // Added by button implementation + removeEvent(wrapper.element, 'mouseenter'); + removeEvent(wrapper.element, 'mouseleave'); + + if (text) { + // Destroy the text element + text = text.destroy(); + } + // Call base implementation to destroy the rest + SVGElement.prototype.destroy.call(wrapper); + } + }); + } + }; // end SVGRenderer + + +// general renderer + Renderer = SVGRenderer; + + + /* **************************************************************************** + * * + * START OF INTERNET EXPLORER <= 8 SPECIFIC CODE * + * * + * For applications and websites that don't need IE support, like platform * + * targeted mobile apps and web apps, this code can be removed. * + * * + *****************************************************************************/ + + /** + * @constructor + */ + var VMLRenderer; + if (!hasSVG && !useCanVG) { + + /** + * The VML element wrapper. + */ + var VMLElement = { + + /** + * Initialize a new VML element wrapper. It builds the markup as a string + * to minimize DOM traffic. + * @param {Object} renderer + * @param {Object} nodeName + */ + init: function (renderer, nodeName) { + var wrapper = this, + markup = ['<', nodeName, ' filled="f" stroked="f"'], + style = ['position: ', ABSOLUTE, ';']; + + // divs and shapes need size + if (nodeName === 'shape' || nodeName === DIV) { + style.push('left:0;top:0;width:1px;height:1px;'); + } + if (docMode8) { + style.push('visibility: ', nodeName === DIV ? HIDDEN : VISIBLE); + } + + markup.push(' style="', style.join(''), '"/>'); + + // create element with default attributes and style + if (nodeName) { + markup = nodeName === DIV || nodeName === 'span' || nodeName === 'img' ? + markup.join('') + : renderer.prepVML(markup); + wrapper.element = createElement(markup); + } + + wrapper.renderer = renderer; + wrapper.attrSetters = {}; + }, + + /** + * Add the node to the given parent + * @param {Object} parent + */ + add: function (parent) { + var wrapper = this, + renderer = wrapper.renderer, + element = wrapper.element, + box = renderer.box, + inverted = parent && parent.inverted, + + // get the parent node + parentNode = parent ? + parent.element || parent : + box; + + + // if the parent group is inverted, apply inversion on all children + if (inverted) { // only on groups + renderer.invertChild(element, parentNode); + } + + // issue #140 workaround - related to #61 and #74 + if (docMode8 && parentNode.gVis === HIDDEN) { + css(element, { visibility: HIDDEN }); + } + + // append it + parentNode.appendChild(element); + + // align text after adding to be able to read offset + wrapper.added = true; + if (wrapper.alignOnAdd && !wrapper.deferUpdateTransform) { + wrapper.updateTransform(); + } + + // fire an event for internal hooks + fireEvent(wrapper, 'add'); + + return wrapper; + }, + + /** + * In IE8 documentMode 8, we need to recursively set the visibility down in the DOM + * tree for nested groups. Related to #61, #586. + */ + toggleChildren: function (element, visibility) { + var childNodes = element.childNodes, + i = childNodes.length; + + while (i--) { + + // apply the visibility + css(childNodes[i], { visibility: visibility }); + + // we have a nested group, apply it to its children again + if (childNodes[i].nodeName === 'DIV') { + this.toggleChildren(childNodes[i], visibility); + } + } + }, + + /** + * VML always uses htmlUpdateTransform + */ + updateTransform: SVGElement.prototype.htmlUpdateTransform, + + /** + * Get or set attributes + */ + attr: function (hash, val) { + var wrapper = this, + key, + value, + i, + result, + element = wrapper.element || {}, + elemStyle = element.style, + nodeName = element.nodeName, + renderer = wrapper.renderer, + symbolName = wrapper.symbolName, + hasSetSymbolSize, + shadows = wrapper.shadows, + skipAttr, + attrSetters = wrapper.attrSetters, + ret = wrapper; + + // single key-value pair + if (isString(hash) && defined(val)) { + key = hash; + hash = {}; + hash[key] = val; + } + + // used as a getter, val is undefined + if (isString(hash)) { + key = hash; + if (key === 'strokeWidth' || key === 'stroke-width') { + ret = wrapper.strokeweight; + } else { + ret = wrapper[key]; + } + + // setter + } else { + for (key in hash) { + value = hash[key]; + skipAttr = false; + + // check for a specific attribute setter + result = attrSetters[key] && attrSetters[key](value, key); + + if (result !== false && value !== null) { // #620 + + if (result !== UNDEFINED) { + value = result; // the attribute setter has returned a new value to set + } + + + // prepare paths + // symbols + if (symbolName && /^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(key)) { + // if one of the symbol size affecting parameters are changed, + // check all the others only once for each call to an element's + // .attr() method + if (!hasSetSymbolSize) { + wrapper.symbolAttr(hash); + + hasSetSymbolSize = true; + } + skipAttr = true; + + } else if (key === 'd') { + value = value || []; + wrapper.d = value.join(' '); // used in getter for animation + + // convert paths + i = value.length; + var convertedPath = []; + while (i--) { + + // Multiply by 10 to allow subpixel precision. + // Substracting half a pixel seems to make the coordinates + // align with SVG, but this hasn't been tested thoroughly + if (isNumber(value[i])) { + convertedPath[i] = mathRound(value[i] * 10) - 5; + } else if (value[i] === 'Z') { // close the path + convertedPath[i] = 'x'; + } else { + convertedPath[i] = value[i]; + } + + } + value = convertedPath.join(' ') || 'x'; + element.path = value; + + // update shadows + if (shadows) { + i = shadows.length; + while (i--) { + shadows[i].path = shadows[i].cutOff ? this.cutOffPath(value, shadows[i].cutOff) : value; + } + } + skipAttr = true; + + // directly mapped to css + } else if (key === 'zIndex' || key === 'visibility') { + + // workaround for #61 and #586 + if (docMode8 && key === 'visibility' && nodeName === 'DIV') { + element.gVis = value; + wrapper.toggleChildren(element, value); + if (value === VISIBLE) { // #74 + value = null; + } + } + + if (value) { + elemStyle[key] = value; + } + + + skipAttr = true; + + // width and height + } else if (key === 'width' || key === 'height') { + + value = mathMax(0, value); // don't set width or height below zero (#311) + + this[key] = value; // used in getter + + // clipping rectangle special + if (wrapper.updateClipping) { + wrapper[key] = value; + wrapper.updateClipping(); + } else { + // normal + elemStyle[key] = value; + } + + skipAttr = true; + + // x and y + } else if (key === 'x' || key === 'y') { + + wrapper[key] = value; // used in getter + elemStyle[{ x: 'left', y: 'top' }[key]] = value; + + // class name + } else if (key === 'class') { + // IE8 Standards mode has problems retrieving the className + element.className = value; + + // stroke + } else if (key === 'stroke') { + + value = renderer.color(value, element, key); + + key = 'strokecolor'; + + // stroke width + } else if (key === 'stroke-width' || key === 'strokeWidth') { + element.stroked = value ? true : false; + key = 'strokeweight'; + wrapper[key] = value; // used in getter, issue #113 + if (isNumber(value)) { + value += PX; + } + + // dashStyle + } else if (key === 'dashstyle') { + var strokeElem = element.getElementsByTagName('stroke')[0] || + createElement(renderer.prepVML(['']), null, null, element); + strokeElem[key] = value || 'solid'; + wrapper.dashstyle = value; + /* because changing stroke-width will change the dash length + and cause an epileptic effect */ + skipAttr = true; + + // fill + } else if (key === 'fill') { + + if (nodeName === 'SPAN') { // text color + elemStyle.color = value; + } else { + element.filled = value !== NONE ? true : false; + + value = renderer.color(value, element, key); + + key = 'fillcolor'; + } + + // rotation on VML elements + } else if (nodeName === 'shape' && key === 'rotation') { + wrapper[key] = value; + + // translation for animation + } else if (key === 'translateX' || key === 'translateY' || key === 'rotation') { + wrapper[key] = value; + wrapper.updateTransform(); + + skipAttr = true; + + // text for rotated and non-rotated elements + } else if (key === 'text') { + this.bBox = null; + element.innerHTML = value; + skipAttr = true; + } + + // let the shadow follow the main element + if (shadows && key === 'visibility') { + i = shadows.length; + while (i--) { + shadows[i].style[key] = value; + } + } + + + if (!skipAttr) { + if (docMode8) { // IE8 setAttribute bug + element[key] = value; + } else { + attr(element, key, value); + } + } + + } + } + } + return ret; + }, + + /** + * Set the element's clipping to a predefined rectangle + * + * @param {String} id The id of the clip rectangle + */ + clip: function (clipRect) { + var wrapper = this, + clipMembers = clipRect.members, + element = wrapper.element, + parentNode = element.parentNode; + + clipMembers.push(wrapper); + wrapper.destroyClip = function () { + erase(clipMembers, wrapper); + }; + + // Issue #863 workaround - related to #140, #61, #74 + if (parentNode && parentNode.className === 'highcharts-tracker' && !docMode8) { + css(element, { visibility: HIDDEN }); + } + + return wrapper.css(clipRect.getCSS(wrapper)); + }, + + /** + * Set styles for the element + * @param {Object} styles + */ + css: SVGElement.prototype.htmlCss, + + /** + * Removes a child either by removeChild or move to garbageBin. + * Issue 490; in VML removeChild results in Orphaned nodes according to sIEve, discardElement does not. + */ + safeRemoveChild: function (element) { + // discardElement will detach the node from its parent before attaching it + // to the garbage bin. Therefore it is important that the node is attached and have parent. + var parentNode = element.parentNode; + if (parentNode) { + discardElement(element); + } + }, + + /** + * Extend element.destroy by removing it from the clip members array + */ + destroy: function () { + var wrapper = this; + + if (wrapper.destroyClip) { + wrapper.destroyClip(); + } + + return SVGElement.prototype.destroy.apply(wrapper); + }, + + /** + * Remove all child nodes of a group, except the v:group element + */ + empty: function () { + var element = this.element, + childNodes = element.childNodes, + i = childNodes.length, + node; + + while (i--) { + node = childNodes[i]; + node.parentNode.removeChild(node); + } + }, + + /** + * Add an event listener. VML override for normalizing event parameters. + * @param {String} eventType + * @param {Function} handler + */ + on: function (eventType, handler) { + // simplest possible event model for internal use + this.element['on' + eventType] = function () { + var evt = win.event; + evt.target = evt.srcElement; + handler(evt); + }; + return this; + }, + + /** + * In stacked columns, cut off the shadows so that they don't overlap + */ + cutOffPath: function (path, length) { + + var len; + + path = path.split(/[ ,]/); + len = path.length; + + if (len === 9 || len === 11) { + path[len - 4] = path[len - 2] = pInt(path[len - 2]) - 10 * length; + } + return path.join(' '); + }, + + /** + * Apply a drop shadow by copying elements and giving them different strokes + * @param {Boolean} apply + */ + shadow: function (apply, group, cutOff) { + var shadows = [], + i, + element = this.element, + renderer = this.renderer, + shadow, + elemStyle = element.style, + markup, + path = element.path, + strokeWidth, + modifiedPath; + + // some times empty paths are not strings + if (path && typeof path.value !== 'string') { + path = 'x'; + } + modifiedPath = path; + + if (apply) { + for (i = 1; i <= 3; i++) { + + strokeWidth = 7 - 2 * i; + + // Cut off shadows for stacked column items + if (cutOff) { + modifiedPath = this.cutOffPath(path.value, strokeWidth + 0.5); + } + + markup = ['']; + + shadow = createElement(renderer.prepVML(markup), + null, { + left: pInt(elemStyle.left) + 1, + top: pInt(elemStyle.top) + 1 + } + ); + if (cutOff) { + shadow.cutOff = strokeWidth + 1; + } + + // apply the opacity + markup = ['']; + createElement(renderer.prepVML(markup), null, null, shadow); + + + // insert it + if (group) { + group.element.appendChild(shadow); + } else { + element.parentNode.insertBefore(shadow, element); + } + + // record it + shadows.push(shadow); + + } + + this.shadows = shadows; + } + return this; + + } + }; + VMLElement = extendClass(SVGElement, VMLElement); + + /** + * The VML renderer + */ + var VMLRendererExtension = { // inherit SVGRenderer + + Element: VMLElement, + isIE8: userAgent.indexOf('MSIE 8.0') > -1, + + + /** + * Initialize the VMLRenderer + * @param {Object} container + * @param {Number} width + * @param {Number} height + */ + init: function (container, width, height) { + var renderer = this, + boxWrapper, + box; + + renderer.alignedObjects = []; + + boxWrapper = renderer.createElement(DIV); + box = boxWrapper.element; + box.style.position = RELATIVE; // for freeform drawing using renderer directly + container.appendChild(boxWrapper.element); + + + // generate the containing box + renderer.box = box; + renderer.boxWrapper = boxWrapper; + + + renderer.setSize(width, height, false); + + // The only way to make IE6 and IE7 print is to use a global namespace. However, + // with IE8 the only way to make the dynamic shapes visible in screen and print mode + // seems to be to add the xmlns attribute and the behaviour style inline. + if (!doc.namespaces.hcv) { + + doc.namespaces.add('hcv', 'urn:schemas-microsoft-com:vml'); + + // setup default css + doc.createStyleSheet().cssText = + 'hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke' + + '{ behavior:url(#default#VML); display: inline-block; } '; + + } + }, + + + /** + * Detect whether the renderer is hidden. This happens when one of the parent elements + * has display: none + */ + isHidden: function () { + return !this.box.offsetWidth; + }, + + /** + * Define a clipping rectangle. In VML it is accomplished by storing the values + * for setting the CSS style to all associated members. + * + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + */ + clipRect: function (x, y, width, height) { + + // create a dummy element + var clipRect = this.createElement(); + + // mimic a rectangle with its style object for automatic updating in attr + return extend(clipRect, { + members: [], + left: x, + top: y, + width: width, + height: height, + getCSS: function (wrapper) { + var inverted = wrapper.inverted, + rect = this, + top = rect.top, + left = rect.left, + right = left + rect.width, + bottom = top + rect.height, + ret = { + clip: 'rect(' + + mathRound(inverted ? left : top) + 'px,' + + mathRound(inverted ? bottom : right) + 'px,' + + mathRound(inverted ? right : bottom) + 'px,' + + mathRound(inverted ? top : left) + 'px)' + }; + + // issue 74 workaround + if (!inverted && docMode8 && wrapper.element.nodeName !== 'IMG') { + extend(ret, { + width: right + PX, + height: bottom + PX + }); + } + + return ret; + }, + + // used in attr and animation to update the clipping of all members + updateClipping: function () { + each(clipRect.members, function (member) { + member.css(clipRect.getCSS(member)); + }); + } + }); + + }, + + + /** + * Take a color and return it if it's a string, make it a gradient if it's a + * gradient configuration object, and apply opacity. + * + * @param {Object} color The color or config object + */ + color: function (color, elem, prop) { + var colorObject, + regexRgba = /^rgba/, + markup, + fillType, + ret = NONE; + + // Check for linear or radial gradient + if (color && color.linearGradient) { + fillType = 'gradient'; + } else if (color && color.radialGradient) { + fillType = 'pattern'; + } + + + if (fillType) { + + var stopColor, + stopOpacity, + gradient = color.linearGradient || color.radialGradient, + x1, + y1, + x2, + y2, + angle, + opacity1, + opacity2, + color1, + color2, + fillAttr = '', + stops = color.stops, + firstStop, + lastStop, + colors = []; + + // Extend from 0 to 1 + firstStop = stops[0]; + lastStop = stops[stops.length - 1]; + if (firstStop[0] > 0) { + stops.unshift([ + 0, + firstStop[1] + ]); + } + if (lastStop[0] < 1) { + stops.push([ + 1, + lastStop[1] + ]); + } + + // Compute the stops + each(stops, function (stop, i) { + if (regexRgba.test(stop[1])) { + colorObject = Color(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } else { + stopColor = stop[1]; + stopOpacity = 1; + } + + // Build the color attribute + colors.push((stop[0] * 100) + '% ' + stopColor); + + // Only start and end opacities are allowed, so we use the first and the last + if (!i) { + opacity1 = stopOpacity; + color2 = stopColor; + } else { + opacity2 = stopOpacity; + color1 = stopColor; + } + }); + + // Handle linear gradient angle + if (fillType === 'gradient') { + x1 = gradient.x1 || gradient[0] || 0; + y1 = gradient.y1 || gradient[1] || 0; + x2 = gradient.x2 || gradient[2] || 0; + y2 = gradient.y2 || gradient[3] || 0; + angle = 90 - math.atan( + (y2 - y1) / // y vector + (x2 - x1) // x vector + ) * 180 / mathPI; + + // Radial (circular) gradient + } else { + // pie: http://jsfiddle.net/highcharts/66g8H/ + // reference: http://jsfiddle.net/highcharts/etznJ/ + // http://jsfiddle.net/highcharts/XRbCc/ + // http://jsfiddle.net/highcharts/F3fwR/ + // TODO: + // - correct for radialRefeence + // - check whether gradient stops are supported + // - add global option for gradient image (must relate to version) + var r = gradient.r, + size = r * 2, + cx = gradient.cx, + cy = gradient.cy; + //radialReference = elem.radialReference; + + //if (radialReference) { + // Try setting pixel size, or other way to adjust the gradient size to the bounding box + //} + fillAttr = 'src="http://code.highcharts.com/gfx/radial-gradient.png" ' + + 'size="' + size + ',' + size + '" ' + + 'origin="0.5,0.5" ' + + 'position="' + cx + ',' + cy + '" ' + + 'color2="' + color2 + '" '; + + // The fill element's color attribute is broken in IE8 standards mode, so we + // need to set the parent shape's fillcolor attribute instead. + ret = color1; + } + + + // Apply the gradient to fills only. + if (prop === 'fill') { + + // when colors attribute is used, the meanings of opacity and o:opacity2 + // are reversed. + markup = ['']; + createElement(this.prepVML(markup), null, null, elem); + + // Gradients are not supported for VML stroke, return the first color. #722. + } else { + ret = stopColor; + } + + + // if the color is an rgba color, split it and add a fill node + // to hold the opacity component + } else if (regexRgba.test(color) && elem.tagName !== 'IMG') { + + colorObject = Color(color); + + markup = ['<', prop, ' opacity="', colorObject.get('a'), '"/>']; + createElement(this.prepVML(markup), null, null, elem); + + ret = colorObject.get('rgb'); + + + } else { + var strokeNodes = elem.getElementsByTagName(prop); + if (strokeNodes.length) { + strokeNodes[0].opacity = 1; + } + ret = color; + } + + return ret; + }, + + /** + * Take a VML string and prepare it for either IE8 or IE6/IE7. + * @param {Array} markup A string array of the VML markup to prepare + */ + prepVML: function (markup) { + var vmlStyle = 'display:inline-block;behavior:url(#default#VML);', + isIE8 = this.isIE8; + + markup = markup.join(''); + + if (isIE8) { // add xmlns and style inline + markup = markup.replace('/>', ' xmlns="urn:schemas-microsoft-com:vml" />'); + if (markup.indexOf('style="') === -1) { + markup = markup.replace('/>', ' style="' + vmlStyle + '" />'); + } else { + markup = markup.replace('style="', 'style="' + vmlStyle); + } + + } else { // add namespace + markup = markup.replace('<', ' 1) { + obj.css({ + left: x, + top: y, + width: width, + height: height + }); + } + return obj; + }, + + /** + * VML uses a shape for rect to overcome bugs and rotation problems + */ + rect: function (x, y, width, height, r, strokeWidth) { + + if (isObject(x)) { + y = x.y; + width = x.width; + height = x.height; + strokeWidth = x.strokeWidth; + x = x.x; + } + var wrapper = this.symbol('rect'); + wrapper.r = r; + + return wrapper.attr(wrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0))); + }, + + /** + * In the VML renderer, each child of an inverted div (group) is inverted + * @param {Object} element + * @param {Object} parentNode + */ + invertChild: function (element, parentNode) { + var parentStyle = parentNode.style; + css(element, { + flip: 'x', + left: pInt(parentStyle.width) - 1, + top: pInt(parentStyle.height) - 1, + rotation: -90 + }); + }, + + /** + * Symbol definitions that override the parent SVG renderer's symbols + * + */ + symbols: { + // VML specific arc function + arc: function (x, y, w, h, options) { + var start = options.start, + end = options.end, + radius = options.r || w || h, + cosStart = mathCos(start), + sinStart = mathSin(start), + cosEnd = mathCos(end), + sinEnd = mathSin(end), + innerRadius = options.innerR, + circleCorrection = 0.08 / radius, // #760 + innerCorrection = (innerRadius && 0.1 / innerRadius) || 0, + ret; + + if (end - start === 0) { // no angle, don't show it. + return ['x']; + + } else if (2 * mathPI - end + start < circleCorrection) { // full circle + // empirical correction found by trying out the limits for different radii + cosEnd = -circleCorrection; + } else if (end - start < innerCorrection) { // issue #186, another mysterious VML arc problem + cosEnd = mathCos(start + innerCorrection); + } + + ret = [ + 'wa', // clockwise arc to + x - radius, // left + y - radius, // top + x + radius, // right + y + radius, // bottom + x + radius * cosStart, // start x + y + radius * sinStart, // start y + x + radius * cosEnd, // end x + y + radius * sinEnd // end y + ]; + + if (options.open) { + ret.push( + M, + x - innerRadius, + y - innerRadius + ); + } + + ret.push( + 'at', // anti clockwise arc to + x - innerRadius, // left + y - innerRadius, // top + x + innerRadius, // right + y + innerRadius, // bottom + x + innerRadius * cosEnd, // start x + y + innerRadius * sinEnd, // start y + x + innerRadius * cosStart, // end x + y + innerRadius * sinStart, // end y + 'x', // finish path + 'e' // close + ); + + return ret; + + }, + // Add circle symbol path. This performs significantly faster than v:oval. + circle: function (x, y, w, h) { + + return [ + 'wa', // clockwisearcto + x, // left + y, // top + x + w, // right + y + h, // bottom + x + w, // start x + y + h / 2, // start y + x + w, // end x + y + h / 2, // end y + //'x', // finish path + 'e' // close + ]; + }, + /** + * Add rectangle symbol path which eases rotation and omits arcsize problems + * compared to the built-in VML roundrect shape + * + * @param {Number} left Left position + * @param {Number} top Top position + * @param {Number} r Border radius + * @param {Object} options Width and height + */ + + rect: function (left, top, width, height, options) { + + var right = left + width, + bottom = top + height, + ret, + r; + + // No radius, return the more lightweight square + if (!defined(options) || !options.r) { + ret = SVGRenderer.prototype.symbols.square.apply(0, arguments); + + // Has radius add arcs for the corners + } else { + + r = mathMin(options.r, width, height); + ret = [ + M, + left + r, top, + + L, + right - r, top, + 'wa', + right - 2 * r, top, + right, top + 2 * r, + right - r, top, + right, top + r, + + L, + right, bottom - r, + 'wa', + right - 2 * r, bottom - 2 * r, + right, bottom, + right, bottom - r, + right - r, bottom, + + L, + left + r, bottom, + 'wa', + left, bottom - 2 * r, + left + 2 * r, bottom, + left + r, bottom, + left, bottom - r, + + L, + left, top + r, + 'wa', + left, top, + left + 2 * r, top + 2 * r, + left, top + r, + left + r, top, + + + 'x', + 'e' + ]; + } + return ret; + } + } + }; + VMLRenderer = function () { + this.init.apply(this, arguments); + }; + VMLRenderer.prototype = merge(SVGRenderer.prototype, VMLRendererExtension); + + // general renderer + Renderer = VMLRenderer; + } + + /* **************************************************************************** + * * + * END OF INTERNET EXPLORER <= 8 SPECIFIC CODE * + * * + *****************************************************************************/ + /* **************************************************************************** + * * + * START OF ANDROID < 3 SPECIFIC CODE. THIS CAN BE REMOVED IF YOU'RE NOT * + * TARGETING THAT SYSTEM. * + * * + *****************************************************************************/ + var CanVGRenderer, + CanVGController; + + if (useCanVG) { + /** + * The CanVGRenderer is empty from start to keep the source footprint small. + * When requested, the CanVGController downloads the rest of the source packaged + * together with the canvg library. + */ + CanVGRenderer = function () { + // Empty constructor + }; + + /** + * Start with an empty symbols object. This is needed when exporting is used (exporting.src.js will add a few symbols), but + * the implementation from SvgRenderer will not be merged in until first render. + */ + CanVGRenderer.prototype.symbols = {}; + + /** + * Handles on demand download of canvg rendering support. + */ + CanVGController = (function () { + // List of renderering calls + var deferredRenderCalls = []; + + /** + * When downloaded, we are ready to draw deferred charts. + */ + function drawDeferred() { + var callLength = deferredRenderCalls.length, + callIndex; + + // Draw all pending render calls + for (callIndex = 0; callIndex < callLength; callIndex++) { + deferredRenderCalls[callIndex](); + } + // Clear the list + deferredRenderCalls = []; + } + + return { + push: function (func, scriptLocation) { + // Only get the script once + if (deferredRenderCalls.length === 0) { + getScript(scriptLocation, drawDeferred); + } + // Register render call + deferredRenderCalls.push(func); + } + }; + }()); + } // end CanVGRenderer + + /* **************************************************************************** + * * + * END OF ANDROID < 3 SPECIFIC CODE * + * * + *****************************************************************************/ + + /** + * General renderer + */ + Renderer = VMLRenderer || CanVGRenderer || SVGRenderer; + /** + * The Tick class + */ + function Tick(axis, pos, type) { + this.axis = axis; + this.pos = pos; + this.type = type || ''; + this.isNew = true; + + if (!type) { + this.addLabel(); + } + } + + Tick.prototype = { + /** + * Write the tick label + */ + addLabel: function () { + var tick = this, + axis = tick.axis, + options = axis.options, + chart = axis.chart, + horiz = axis.horiz, + categories = axis.categories, + pos = tick.pos, + labelOptions = options.labels, + str, + tickPositions = axis.tickPositions, + width = (categories && horiz && categories.length && !labelOptions.step && !labelOptions.staggerLines && !labelOptions.rotation && + chart.plotWidth / tickPositions.length) || + (!horiz && chart.plotWidth / 2), + isFirst = pos === tickPositions[0], + isLast = pos === tickPositions[tickPositions.length - 1], + css, + attr, + value = categories && defined(categories[pos]) ? categories[pos] : pos, + label = tick.label, + tickPositionInfo = tickPositions.info, + dateTimeLabelFormat; + + // Set the datetime label format. If a higher rank is set for this position, use that. If not, + // use the general format. + if (axis.isDatetimeAxis && tickPositionInfo) { + dateTimeLabelFormat = options.dateTimeLabelFormats[tickPositionInfo.higherRanks[pos] || tickPositionInfo.unitName]; + } + + // set properties for access in render method + tick.isFirst = isFirst; + tick.isLast = isLast; + + // get the string + str = axis.labelFormatter.call({ + axis: axis, + chart: chart, + isFirst: isFirst, + isLast: isLast, + dateTimeLabelFormat: dateTimeLabelFormat, + value: axis.isLog ? correctFloat(lin2log(value)) : value + }); + + // prepare CSS + css = width && { width: mathMax(1, mathRound(width - 2 * (labelOptions.padding || 10))) + PX }; + css = extend(css, labelOptions.style); + + // first call + if (!defined(label)) { + attr = { + align: labelOptions.align + }; + if (isNumber(labelOptions.rotation)) { + attr.rotation = labelOptions.rotation; + } + tick.label = + defined(str) && labelOptions.enabled ? + chart.renderer.text( + str, + 0, + 0, + labelOptions.useHTML + ) + .attr(attr) + // without position absolute, IE export sometimes is wrong + .css(css) + .add(axis.axisGroup) : + null; + + // update + } else if (label) { + label.attr({ + text: str + }) + .css(css); + } + }, + + /** + * Get the offset height or width of the label + */ + getLabelSize: function () { + var label = this.label, + axis = this.axis; + return label ? + ((this.labelBBox = label.getBBox(true)))[axis.horiz ? 'height' : 'width'] : + 0; + }, + + /** + * Find how far the labels extend to the right and left of the tick's x position. Used for anti-collision + * detection with overflow logic. + */ + getLabelSides: function () { + var bBox = this.labelBBox, // assume getLabelSize has run at this point + axis = this.axis, + options = axis.options, + labelOptions = options.labels, + width = bBox.width, + leftSide = width * { left: 0, center: 0.5, right: 1 }[labelOptions.align] - labelOptions.x; + + return [-leftSide, width - leftSide]; + }, + + /** + * Handle the label overflow by adjusting the labels to the left and right edge, or + * hide them if they collide into the neighbour label. + */ + handleOverflow: function (index, xy) { + var show = true, + axis = this.axis, + chart = axis.chart, + isFirst = this.isFirst, + isLast = this.isLast, + x = xy.x, + reversed = axis.reversed, + tickPositions = axis.tickPositions; + + if (isFirst || isLast) { + + var sides = this.getLabelSides(), + leftSide = sides[0], + rightSide = sides[1], + plotLeft = chart.plotLeft, + plotRight = plotLeft + axis.len, + neighbour = axis.ticks[tickPositions[index + (isFirst ? 1 : -1)]], + neighbourEdge = neighbour && neighbour.label.xy.x + neighbour.getLabelSides()[isFirst ? 0 : 1]; + + if ((isFirst && !reversed) || (isLast && reversed)) { + // Is the label spilling out to the left of the plot area? + if (x + leftSide < plotLeft) { + + // Align it to plot left + x = plotLeft - leftSide; + + // Hide it if it now overlaps the neighbour label + if (neighbour && x + rightSide > neighbourEdge) { + show = false; + } + } + + } else { + // Is the label spilling out to the right of the plot area? + if (x + rightSide > plotRight) { + + // Align it to plot right + x = plotRight - rightSide; + + // Hide it if it now overlaps the neighbour label + if (neighbour && x + leftSide < neighbourEdge) { + show = false; + } + + } + } + + // Set the modified x position of the label + xy.x = x; + } + return show; + }, + + /** + * Get the x and y position for ticks and labels + */ + getPosition: function (horiz, pos, tickmarkOffset, old) { + var axis = this.axis, + chart = axis.chart, + cHeight = (old && chart.oldChartHeight) || chart.chartHeight; + + return { + x: horiz ? + axis.translate(pos + tickmarkOffset, null, null, old) + axis.transB : + axis.left + axis.offset + (axis.opposite ? ((old && chart.oldChartWidth) || chart.chartWidth) - axis.right - axis.left : 0), + + y: horiz ? + cHeight - axis.bottom + axis.offset - (axis.opposite ? axis.height : 0) : + cHeight - axis.translate(pos + tickmarkOffset, null, null, old) - axis.transB + }; + + }, + + /** + * Get the x, y position of the tick label + */ + getLabelPosition: function (x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var axis = this.axis, + transA = axis.transA, + reversed = axis.reversed, + staggerLines = axis.staggerLines; + + x = x + labelOptions.x - (tickmarkOffset && horiz ? + tickmarkOffset * transA * (reversed ? -1 : 1) : 0); + y = y + labelOptions.y - (tickmarkOffset && !horiz ? + tickmarkOffset * transA * (reversed ? 1 : -1) : 0); + + // Vertically centered + if (!defined(labelOptions.y)) { + y += pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2; + } + + // Correct for staggered labels + if (staggerLines) { + y += (index / (step || 1) % staggerLines) * 16; + } + + return { + x: x, + y: y + }; + }, + + /** + * Extendible method to return the path of the marker + */ + getMarkPath: function (x, y, tickLength, tickWidth, horiz, renderer) { + return renderer.crispLine([ + M, + x, + y, + L, + x + (horiz ? 0 : -tickLength), + y + (horiz ? tickLength : 0) + ], tickWidth); + }, + + /** + * Put everything in place + * + * @param index {Number} + * @param old {Boolean} Use old coordinates to prepare an animation into new position + */ + render: function (index, old) { + var tick = this, + axis = tick.axis, + options = axis.options, + chart = axis.chart, + renderer = chart.renderer, + horiz = axis.horiz, + type = tick.type, + label = tick.label, + pos = tick.pos, + labelOptions = options.labels, + gridLine = tick.gridLine, + gridPrefix = type ? type + 'Grid' : 'grid', + tickPrefix = type ? type + 'Tick' : 'tick', + gridLineWidth = options[gridPrefix + 'LineWidth'], + gridLineColor = options[gridPrefix + 'LineColor'], + dashStyle = options[gridPrefix + 'LineDashStyle'], + tickLength = options[tickPrefix + 'Length'], + tickWidth = options[tickPrefix + 'Width'] || 0, + tickColor = options[tickPrefix + 'Color'], + tickPosition = options[tickPrefix + 'Position'], + gridLinePath, + mark = tick.mark, + markPath, + step = labelOptions.step, + attribs, + show = true, + tickmarkOffset = (options.categories && options.tickmarkPlacement === 'between') ? 0.5 : 0, + xy = tick.getPosition(horiz, pos, tickmarkOffset, old), + x = xy.x, + y = xy.y, + staggerLines = axis.staggerLines; + + // create the grid line + if (gridLineWidth) { + gridLinePath = axis.getPlotLinePath(pos + tickmarkOffset, gridLineWidth, old); + + if (gridLine === UNDEFINED) { + attribs = { + stroke: gridLineColor, + 'stroke-width': gridLineWidth + }; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + if (!type) { + attribs.zIndex = 1; + } + tick.gridLine = gridLine = + gridLineWidth ? + renderer.path(gridLinePath) + .attr(attribs).add(axis.gridGroup) : + null; + } + + // If the parameter 'old' is set, the current call will be followed + // by another call, therefore do not do any animations this time + if (!old && gridLine && gridLinePath) { + gridLine[tick.isNew ? 'attr' : 'animate']({ + d: gridLinePath + }); + } + } + + // create the tick mark + if (tickWidth) { + + // negate the length + if (tickPosition === 'inside') { + tickLength = -tickLength; + } + if (axis.opposite) { + tickLength = -tickLength; + } + + markPath = tick.getMarkPath(x, y, tickLength, tickWidth, horiz, renderer); + + if (mark) { // updating + mark.animate({ + d: markPath + }); + } else { // first time + tick.mark = renderer.path( + markPath + ).attr({ + stroke: tickColor, + 'stroke-width': tickWidth + }).add(axis.axisGroup); + } + } + + // the label is created on init - now move it into place + if (label && !isNaN(x)) { + label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step); + + // apply show first and show last + if ((tick.isFirst && !pick(options.showFirstLabel, 1)) || + (tick.isLast && !pick(options.showLastLabel, 1))) { + show = false; + + // Handle label overflow and show or hide accordingly + } else if (!staggerLines && horiz && labelOptions.overflow === 'justify' && !tick.handleOverflow(index, xy)) { + show = false; + } + + // apply step + if (step && index % step) { + // show those indices dividable by step + show = false; + } + + // Set the new position, and show or hide + if (show) { + label[tick.isNew ? 'attr' : 'animate'](xy); + label.show(); + tick.isNew = false; + } else { + label.hide(); + } + } + }, + + /** + * Destructor for the tick prototype + */ + destroy: function () { + destroyObjectProperties(this, this.axis); + } + }; + + /** + * The object wrapper for plot lines and plot bands + * @param {Object} options + */ + function PlotLineOrBand(axis, options) { + this.axis = axis; + + if (options) { + this.options = options; + this.id = options.id; + } + + //plotLine.render() + return this; + } + + PlotLineOrBand.prototype = { + + /** + * Render the plot line or plot band. If it is already existing, + * move it. + */ + render: function () { + var plotLine = this, + axis = plotLine.axis, + horiz = axis.horiz, + halfPointRange = (axis.pointRange || 0) / 2, + options = plotLine.options, + optionsLabel = options.label, + label = plotLine.label, + width = options.width, + to = options.to, + from = options.from, + isBand = defined(from) && defined(to), + value = options.value, + dashStyle = options.dashStyle, + svgElem = plotLine.svgElem, + path = [], + addEvent, + eventType, + xs, + ys, + x, + y, + color = options.color, + zIndex = options.zIndex, + events = options.events, + attribs, + renderer = axis.chart.renderer; + + // logarithmic conversion + if (axis.isLog) { + from = log2lin(from); + to = log2lin(to); + value = log2lin(value); + } + + // plot line + if (width) { + path = axis.getPlotLinePath(value, width); + attribs = { + stroke: color, + 'stroke-width': width + }; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + } else if (isBand) { // plot band + + // keep within plot area + from = mathMax(from, axis.min - halfPointRange); + to = mathMin(to, axis.max + halfPointRange); + + path = axis.getPlotBandPath(from, to, options); + attribs = { + fill: color + }; + if (options.borderWidth) { + attribs.stroke = options.borderColor; + attribs['stroke-width'] = options.borderWidth; + } + } else { + return; + } + // zIndex + if (defined(zIndex)) { + attribs.zIndex = zIndex; + } + + // common for lines and bands + if (svgElem) { + if (path) { + svgElem.animate({ + d: path + }, null, svgElem.onGetPath); + } else { + svgElem.hide(); + svgElem.onGetPath = function () { + svgElem.show(); + }; + } + } else if (path && path.length) { + plotLine.svgElem = svgElem = renderer.path(path) + .attr(attribs).add(); + + // events + if (events) { + addEvent = function (eventType) { + svgElem.on(eventType, function (e) { + events[eventType].apply(plotLine, [e]); + }); + }; + for (eventType in events) { + addEvent(eventType); + } + } + } + + // the plot band/line label + if (optionsLabel && defined(optionsLabel.text) && path && path.length && axis.width > 0 && axis.height > 0) { + // apply defaults + optionsLabel = merge({ + align: horiz && isBand && 'center', + x: horiz ? !isBand && 4 : 10, + verticalAlign: !horiz && isBand && 'middle', + y: horiz ? isBand ? 16 : 10 : isBand ? 6 : -4, + rotation: horiz && !isBand && 90 + }, optionsLabel); + + // add the SVG element + if (!label) { + plotLine.label = label = renderer.text( + optionsLabel.text, + 0, + 0 + ) + .attr({ + align: optionsLabel.textAlign || optionsLabel.align, + rotation: optionsLabel.rotation, + zIndex: zIndex + }) + .css(optionsLabel.style) + .add(); + } + + // get the bounding box and align the label + xs = [path[1], path[4], pick(path[6], path[1])]; + ys = [path[2], path[5], pick(path[7], path[2])]; + x = arrayMin(xs); + y = arrayMin(ys); + + label.align(optionsLabel, false, { + x: x, + y: y, + width: arrayMax(xs) - x, + height: arrayMax(ys) - y + }); + label.show(); + + } else if (label) { // move out of sight + label.hide(); + } + + // chainable + return plotLine; + }, + + /** + * Remove the plot line or band + */ + destroy: function () { + var plotLine = this, + axis = plotLine.axis; + + // remove it from the lookup + erase(axis.plotLinesAndBands, plotLine); + + destroyObjectProperties(plotLine, this.axis); + } + }; + /** + * The class for stack items + */ + function StackItem(axis, options, isNegative, x, stackOption) { + var inverted = axis.chart.inverted; + + this.axis = axis; + + // Tells if the stack is negative + this.isNegative = isNegative; + + // Save the options to be able to style the label + this.options = options; + + // Save the x value to be able to position the label later + this.x = x; + + // Save the stack option on the series configuration object + this.stack = stackOption; + + // The align options and text align varies on whether the stack is negative and + // if the chart is inverted or not. + // First test the user supplied value, then use the dynamic. + this.alignOptions = { + align: options.align || (inverted ? (isNegative ? 'left' : 'right') : 'center'), + verticalAlign: options.verticalAlign || (inverted ? 'middle' : (isNegative ? 'bottom' : 'top')), + y: pick(options.y, inverted ? 4 : (isNegative ? 14 : -6)), + x: pick(options.x, inverted ? (isNegative ? -6 : 6) : 0) + }; + + this.textAlign = options.textAlign || (inverted ? (isNegative ? 'right' : 'left') : 'center'); + } + + StackItem.prototype = { + destroy: function () { + destroyObjectProperties(this, this.axis); + }, + + /** + * Sets the total of this stack. Should be called when a serie is hidden or shown + * since that will affect the total of other stacks. + */ + setTotal: function (total) { + this.total = total; + this.cum = total; + }, + + /** + * Renders the stack total label and adds it to the stack label group. + */ + render: function (group) { + var str = this.options.formatter.call(this); // format the text in the label + + // Change the text to reflect the new total and set visibility to hidden in case the serie is hidden + if (this.label) { + this.label.attr({text: str, visibility: HIDDEN}); + // Create new label + } else { + this.label = + this.axis.chart.renderer.text(str, 0, 0) // dummy positions, actual position updated with setOffset method in columnseries + .css(this.options.style) // apply style + .attr({align: this.textAlign, // fix the text-anchor + rotation: this.options.rotation, // rotation + visibility: HIDDEN }) // hidden until setOffset is called + .add(group); // add to the labels-group + } + }, + + /** + * Sets the offset that the stack has from the x value and repositions the label. + */ + setOffset: function (xOffset, xWidth) { + var stackItem = this, + axis = stackItem.axis, + chart = axis.chart, + inverted = chart.inverted, + neg = this.isNegative, // special treatment is needed for negative stacks + y = axis.translate(this.total, 0, 0, 0, 1), // stack value translated mapped to chart coordinates + yZero = axis.translate(0), // stack origin + h = mathAbs(y - yZero), // stack height + x = chart.xAxis[0].translate(this.x) + xOffset, // stack x position + plotHeight = chart.plotHeight, + stackBox = { // this is the box for the complete stack + x: inverted ? (neg ? y : y - h) : x, + y: inverted ? plotHeight - x - xWidth : (neg ? (plotHeight - y - h) : plotHeight - y), + width: inverted ? h : xWidth, + height: inverted ? xWidth : h + }; + + if (this.label) { + this.label + .align(this.alignOptions, null, stackBox) // align the label to the box + .attr({visibility: VISIBLE}); // set visibility + } + + } + }; + /** + * Create a new axis object + * @param {Object} chart + * @param {Object} options + */ + function Axis() { + this.init.apply(this, arguments); + } + + Axis.prototype = { + + /** + * Default options for the X axis - the Y axis has extended defaults + */ + defaultOptions: { + // allowDecimals: null, + // alternateGridColor: null, + // categories: [], + dateTimeLabelFormats: { + millisecond: '%H:%M:%S.%L', + second: '%H:%M:%S', + minute: '%H:%M', + hour: '%H:%M', + day: '%e. %b', + week: '%e. %b', + month: '%b \'%y', + year: '%Y' + }, + endOnTick: false, + gridLineColor: '#C0C0C0', + // gridLineDashStyle: 'solid', + // gridLineWidth: 0, + // reversed: false, + + labels: defaultLabelOptions, + // { step: null }, + lineColor: '#C0D0E0', + lineWidth: 1, + //linkedTo: null, + //max: undefined, + //min: undefined, + minPadding: 0.01, + maxPadding: 0.01, + //minRange: null, + minorGridLineColor: '#E0E0E0', + // minorGridLineDashStyle: null, + minorGridLineWidth: 1, + minorTickColor: '#A0A0A0', + //minorTickInterval: null, + minorTickLength: 2, + minorTickPosition: 'outside', // inside or outside + //minorTickWidth: 0, + //opposite: false, + //offset: 0, + //plotBands: [{ + // events: {}, + // zIndex: 1, + // labels: { align, x, verticalAlign, y, style, rotation, textAlign } + //}], + //plotLines: [{ + // events: {} + // dashStyle: {} + // zIndex: + // labels: { align, x, verticalAlign, y, style, rotation, textAlign } + //}], + //reversed: false, + // showFirstLabel: true, + // showLastLabel: true, + startOfWeek: 1, + startOnTick: false, + tickColor: '#C0D0E0', + //tickInterval: null, + tickLength: 5, + tickmarkPlacement: 'between', // on or between + tickPixelInterval: 100, + tickPosition: 'outside', + tickWidth: 1, + title: { + //text: null, + align: 'middle', // low, middle or high + //margin: 0 for horizontal, 10 for vertical axes, + //rotation: 0, + //side: 'outside', + style: { + color: '#6D869F', + //font: defaultFont.replace('normal', 'bold') + fontWeight: 'bold' + } + //x: 0, + //y: 0 + }, + type: 'linear' // linear, logarithmic or datetime + }, + + /** + * This options set extends the defaultOptions for Y axes + */ + defaultYAxisOptions: { + endOnTick: true, + gridLineWidth: 1, + tickPixelInterval: 72, + showLastLabel: true, + labels: { + align: 'right', + x: -8, + y: 3 + }, + lineWidth: 0, + maxPadding: 0.05, + minPadding: 0.05, + startOnTick: true, + tickWidth: 0, + title: { + rotation: 270, + text: 'Y-values' + }, + stackLabels: { + enabled: false, + //align: dynamic, + //y: dynamic, + //x: dynamic, + //verticalAlign: dynamic, + //textAlign: dynamic, + //rotation: 0, + formatter: function () { + return this.total; + }, + style: defaultLabelOptions.style + } + }, + + /** + * These options extend the defaultOptions for left axes + */ + defaultLeftAxisOptions: { + labels: { + align: 'right', + x: -8, + y: null + }, + title: { + rotation: 270 + } + }, + + /** + * These options extend the defaultOptions for right axes + */ + defaultRightAxisOptions: { + labels: { + align: 'left', + x: 8, + y: null + }, + title: { + rotation: 90 + } + }, + + /** + * These options extend the defaultOptions for bottom axes + */ + defaultBottomAxisOptions: { + labels: { + align: 'center', + x: 0, + y: 14 + // overflow: undefined, + // staggerLines: null + }, + title: { + rotation: 0 + } + }, + /** + * These options extend the defaultOptions for left axes + */ + defaultTopAxisOptions: { + labels: { + align: 'center', + x: 0, + y: -5 + // overflow: undefined + // staggerLines: null + }, + title: { + rotation: 0 + } + }, + + /** + * Initialize the axis + */ + init: function (chart, userOptions) { + + + var isXAxis = userOptions.isX, + axis = this; + + // Flag, is the axis horizontal + axis.horiz = chart.inverted ? !isXAxis : isXAxis; + + // Flag, isXAxis + axis.isXAxis = isXAxis; + axis.xOrY = isXAxis ? 'x' : 'y'; + + + axis.opposite = userOptions.opposite; // needed in setOptions + axis.side = axis.horiz ? + (axis.opposite ? 0 : 2) : // top : bottom + (axis.opposite ? 1 : 3); // right : left + + axis.setOptions(userOptions); + + + var options = this.options, + type = options.type, + isDatetimeAxis = type === 'datetime'; + + axis.labelFormatter = options.labels.formatter || axis.defaultLabelFormatter; // can be overwritten by dynamic format + + + // Flag, stagger lines or not + axis.staggerLines = axis.horiz && options.labels.staggerLines; + axis.userOptions = userOptions; + + //axis.axisTitleMargin = UNDEFINED,// = options.title.margin, + axis.minPixelPadding = 0; + //axis.ignoreMinPadding = UNDEFINED; // can be set to true by a column or bar series + //axis.ignoreMaxPadding = UNDEFINED; + + axis.chart = chart; + axis.reversed = options.reversed; + + // Initial categories + axis.categories = options.categories; + + // Elements + //axis.axisGroup = UNDEFINED; + //axis.gridGroup = UNDEFINED; + //axis.axisTitle = UNDEFINED; + //axis.axisLine = UNDEFINED; + + // Flag if type === logarithmic + axis.isLog = type === 'logarithmic'; + + // Flag, if axis is linked to another axis + axis.isLinked = defined(options.linkedTo); + // Linked axis. + //axis.linkedParent = UNDEFINED; + + // Flag if type === datetime + axis.isDatetimeAxis = isDatetimeAxis; + + // Flag if percentage mode + //axis.usePercentage = UNDEFINED; + + + // Tick positions + //axis.tickPositions = UNDEFINED; // array containing predefined positions + // Tick intervals + //axis.tickInterval = UNDEFINED; + //axis.minorTickInterval = UNDEFINED; + + // Major ticks + axis.ticks = {}; + // Minor ticks + axis.minorTicks = {}; + //axis.tickAmount = UNDEFINED; + + // List of plotLines/Bands + axis.plotLinesAndBands = []; + + // Alternate bands + axis.alternateBands = {}; + + // Axis metrics + //axis.left = UNDEFINED; + //axis.top = UNDEFINED; + //axis.width = UNDEFINED; + //axis.height = UNDEFINED; + //axis.bottom = UNDEFINED; + //axis.right = UNDEFINED; + //axis.transA = UNDEFINED; + //axis.transB = UNDEFINED; + //axis.oldTransA = UNDEFINED; + axis.len = 0; + //axis.oldMin = UNDEFINED; + //axis.oldMax = UNDEFINED; + //axis.oldUserMin = UNDEFINED; + //axis.oldUserMax = UNDEFINED; + //axis.oldAxisLength = UNDEFINED; + axis.minRange = axis.userMinRange = options.minRange || options.maxZoom; + axis.range = options.range; + axis.offset = options.offset || 0; + + + // Dictionary for stacks + axis.stacks = {}; + + // Min and max in the data + //axis.dataMin = UNDEFINED, + //axis.dataMax = UNDEFINED, + + // The axis range + axis.max = null; + axis.min = null; + + // User set min and max + //axis.userMin = UNDEFINED, + //axis.userMax = UNDEFINED, + + // Run Axis + + var eventType, + events = axis.options.events; + + // Register + chart.axes.push(axis); + chart[isXAxis ? 'xAxis' : 'yAxis'].push(axis); + + axis.series = []; // populated by Series + + // inverted charts have reversed xAxes as default + if (chart.inverted && isXAxis && axis.reversed === UNDEFINED) { + axis.reversed = true; + } + + axis.removePlotBand = axis.removePlotBandOrLine; + axis.removePlotLine = axis.removePlotBandOrLine; + axis.addPlotBand = axis.addPlotBandOrLine; + axis.addPlotLine = axis.addPlotBandOrLine; + + + // register event listeners + for (eventType in events) { + addEvent(axis, eventType, events[eventType]); + } + + // extend logarithmic axis + if (axis.isLog) { + axis.val2lin = log2lin; + axis.lin2val = lin2log; + } + }, + + /** + * Merge and set options + */ + setOptions: function (userOptions) { + this.options = merge( + this.defaultOptions, + this.isXAxis ? {} : this.defaultYAxisOptions, + [this.defaultTopAxisOptions, this.defaultRightAxisOptions, + this.defaultBottomAxisOptions, this.defaultLeftAxisOptions][this.side], + userOptions + ); + }, + + + /** + * The default label formatter. The context is a special config object for the label. + */ + defaultLabelFormatter: function () { + var axis = this.axis, + value = this.value, + categories = axis.categories, + tickInterval = axis.tickInterval, + dateTimeLabelFormat = this.dateTimeLabelFormat, + ret; + + if (categories) { + ret = value; + + } else if (dateTimeLabelFormat) { // datetime axis + ret = dateFormat(dateTimeLabelFormat, value); + + } else if (tickInterval % 1000000 === 0) { // use M abbreviation + ret = (value / 1000000) + 'M'; + + } else if (tickInterval % 1000 === 0) { // use k abbreviation + ret = (value / 1000) + 'k'; + + } else if (value >= 1000) { // add thousands separators + ret = numberFormat(value, 0); + + } else { // small numbers + ret = numberFormat(value, -1); + } + return ret; + }, + + /** + * Get the minimum and maximum for the series of each axis + */ + getSeriesExtremes: function () { + var axis = this, + chart = axis.chart, + stacks = axis.stacks, + posStack = [], + negStack = [], + i; + + // reset dataMin and dataMax in case we're redrawing + axis.dataMin = axis.dataMax = null; + + // loop through this axis' series + each(axis.series, function (series) { + + if (series.visible || !chart.options.chart.ignoreHiddenSeries) { + + var seriesOptions = series.options, + stacking, + posPointStack, + negPointStack, + stackKey, + stackOption, + negKey, + xData, + yData, + x, + y, + threshold = seriesOptions.threshold, + yDataLength, + activeYData = [], + activeCounter = 0; + + // Validate threshold in logarithmic axes + if (axis.isLog && threshold <= 0) { + threshold = seriesOptions.threshold = null; + } + + // Get dataMin and dataMax for X axes + if (axis.isXAxis) { + xData = series.xData; + if (xData.length) { + axis.dataMin = mathMin(pick(axis.dataMin, xData[0]), arrayMin(xData)); + axis.dataMax = mathMax(pick(axis.dataMax, xData[0]), arrayMax(xData)); + } + + // Get dataMin and dataMax for Y axes, as well as handle stacking and processed data + } else { + var isNegative, + pointStack, + key, + cropped = series.cropped, + xExtremes = series.xAxis.getExtremes(), + //findPointRange, + //pointRange, + j, + hasModifyValue = !!series.modifyValue; + + + // Handle stacking + stacking = seriesOptions.stacking; + axis.usePercentage = stacking === 'percent'; + + // create a stack for this particular series type + if (stacking) { + stackOption = seriesOptions.stack; + stackKey = series.type + pick(stackOption, ''); + negKey = '-' + stackKey; + series.stackKey = stackKey; // used in translate + + posPointStack = posStack[stackKey] || []; // contains the total values for each x + posStack[stackKey] = posPointStack; + + negPointStack = negStack[negKey] || []; + negStack[negKey] = negPointStack; + } + if (axis.usePercentage) { + axis.dataMin = 0; + axis.dataMax = 99; + } + + // processData can alter series.pointRange, so this goes after + //findPointRange = series.pointRange === null; + + xData = series.processedXData; + yData = series.processedYData; + yDataLength = yData.length; + + // loop over the non-null y values and read them into a local array + for (i = 0; i < yDataLength; i++) { + x = xData[i]; + y = yData[i]; + if (y !== null && y !== UNDEFINED) { + + // read stacked values into a stack based on the x value, + // the sign of y and the stack key + if (stacking) { + isNegative = y < threshold; + pointStack = isNegative ? negPointStack : posPointStack; + key = isNegative ? negKey : stackKey; + + y = pointStack[x] = + defined(pointStack[x]) ? + pointStack[x] + y : y; + + + // add the series + if (!stacks[key]) { + stacks[key] = {}; + } + + // If the StackItem is there, just update the values, + // if not, create one first + if (!stacks[key][x]) { + stacks[key][x] = new StackItem(axis, axis.options.stackLabels, isNegative, x, stackOption); + } + stacks[key][x].setTotal(y); + + + // general hook, used for Highstock compare values feature + } else if (hasModifyValue) { + y = series.modifyValue(y); + } + + // get the smallest distance between points + /*if (i) { + distance = mathAbs(xData[i] - xData[i - 1]); + pointRange = pointRange === UNDEFINED ? distance : mathMin(distance, pointRange); + }*/ + + // for points within the visible range, including the first point outside the + // visible range, consider y extremes + if (cropped || ((xData[i + 1] || x) >= xExtremes.min && (xData[i - 1] || x) <= xExtremes.max)) { + + j = y.length; + if (j) { // array, like ohlc or range data + while (j--) { + if (y[j] !== null) { + activeYData[activeCounter++] = y[j]; + } + } + } else { + activeYData[activeCounter++] = y; + } + } + } + } + + // record the least unit distance + /*if (findPointRange) { + series.pointRange = pointRange || 1; + } + series.closestPointRange = pointRange;*/ + + // Get the dataMin and dataMax so far. If percentage is used, the min and max are + // always 0 and 100. If the length of activeYData is 0, continue with null values. + if (!axis.usePercentage && activeYData.length) { + axis.dataMin = mathMin(pick(axis.dataMin, activeYData[0]), arrayMin(activeYData)); + axis.dataMax = mathMax(pick(axis.dataMax, activeYData[0]), arrayMax(activeYData)); + } + + // Adjust to threshold + if (defined(threshold)) { + if (axis.dataMin >= threshold) { + axis.dataMin = threshold; + axis.ignoreMinPadding = true; + } else if (axis.dataMax < threshold) { + axis.dataMax = threshold; + axis.ignoreMaxPadding = true; + } + } + } + } + }); + }, + + /** + * Translate from axis value to pixel position on the chart, or back + * + */ + translate: function (val, backwards, cvsCoord, old, handleLog) { + var axis = this, + axisLength = axis.len, + sign = 1, + cvsOffset = 0, + localA = old ? axis.oldTransA : axis.transA, + localMin = old ? axis.oldMin : axis.min, + returnValue, + postTranslate = axis.options.ordinal || (axis.isLog && handleLog); + + if (!localA) { + localA = axis.transA; + } + + if (cvsCoord) { + sign *= -1; // canvas coordinates inverts the value + cvsOffset = axisLength; + } + if (axis.reversed) { // reversed axis + sign *= -1; + cvsOffset -= sign * axisLength; + } + + if (backwards) { // reverse translation + if (axis.reversed) { + val = axisLength - val; + } + returnValue = val / localA + localMin; // from chart pixel to value + if (postTranslate) { // log and ordinal axes + returnValue = axis.lin2val(returnValue); + } + + } else { // normal translation, from axis value to pixel, relative to plot + if (postTranslate) { // log and ordinal axes + val = axis.val2lin(val); + } + + returnValue = sign * (val - localMin) * localA + cvsOffset + (sign * axis.minPixelPadding); + } + + return returnValue; + }, + + /** + * Create the path for a plot line that goes from the given value on + * this axis, across the plot to the opposite side + * @param {Number} value + * @param {Number} lineWidth Used for calculation crisp line + * @param {Number] old Use old coordinates (for resizing and rescaling) + */ + getPlotLinePath: function (value, lineWidth, old) { + var axis = this, + chart = axis.chart, + axisLeft = axis.left, + axisTop = axis.top, + x1, + y1, + x2, + y2, + translatedValue = axis.translate(value, null, null, old), + cHeight = (old && chart.oldChartHeight) || chart.chartHeight, + cWidth = (old && chart.oldChartWidth) || chart.chartWidth, + skip, + transB = axis.transB; + + x1 = x2 = mathRound(translatedValue + transB); + y1 = y2 = mathRound(cHeight - translatedValue - transB); + + if (isNaN(translatedValue)) { // no min or max + skip = true; + + } else if (axis.horiz) { + y1 = axisTop; + y2 = cHeight - axis.bottom; + if (x1 < axisLeft || x1 > axisLeft + axis.width) { + skip = true; + } + } else { + x1 = axisLeft; + x2 = cWidth - axis.right; + + if (y1 < axisTop || y1 > axisTop + axis.height) { + skip = true; + } + } + return skip ? + null : + chart.renderer.crispLine([M, x1, y1, L, x2, y2], lineWidth || 0); + }, + + /** + * Create the path for a plot band + */ + getPlotBandPath: function (from, to) { + + var toPath = this.getPlotLinePath(to), + path = this.getPlotLinePath(from); + + if (path && toPath) { + path.push( + toPath[4], + toPath[5], + toPath[1], + toPath[2] + ); + } else { // outside the axis area + path = null; + } + + return path; + }, + + /** + * Set the tick positions of a linear axis to round values like whole tens or every five. + */ + getLinearTickPositions: function (tickInterval, min, max) { + var pos, + lastPos, + roundedMin = correctFloat(mathFloor(min / tickInterval) * tickInterval), + roundedMax = correctFloat(mathCeil(max / tickInterval) * tickInterval), + tickPositions = []; + + // Populate the intermediate values + pos = roundedMin; + while (pos <= roundedMax) { + + // Place the tick on the rounded value + tickPositions.push(pos); + + // Always add the raw tickInterval, not the corrected one. + pos = correctFloat(pos + tickInterval); + + // If the interval is not big enough in the current min - max range to actually increase + // the loop variable, we need to break out to prevent endless loop. Issue #619 + if (pos === lastPos) { + break; + } + + // Record the last value + lastPos = pos; + } + return tickPositions; + }, + + /** + * Set the tick positions of a logarithmic axis + */ + getLogTickPositions: function (interval, min, max, minor) { + var axis = this, + options = axis.options, + axisLength = axis.len; + + // Since we use this method for both major and minor ticks, + // use a local variable and return the result + var positions = []; + + // Reset + if (!minor) { + axis._minorAutoInterval = null; + } + + // First case: All ticks fall on whole logarithms: 1, 10, 100 etc. + if (interval >= 0.5) { + interval = mathRound(interval); + positions = axis.getLinearTickPositions(interval, min, max); + + // Second case: We need intermediary ticks. For example + // 1, 2, 4, 6, 8, 10, 20, 40 etc. + } else if (interval >= 0.08) { + var roundedMin = mathFloor(min), + intermediate, + i, + j, + len, + pos, + lastPos, + break2; + + if (interval > 0.3) { + intermediate = [1, 2, 4]; + } else if (interval > 0.15) { // 0.2 equals five minor ticks per 1, 10, 100 etc + intermediate = [1, 2, 4, 6, 8]; + } else { // 0.1 equals ten minor ticks per 1, 10, 100 etc + intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + } + + for (i = roundedMin; i < max + 1 && !break2; i++) { + len = intermediate.length; + for (j = 0; j < len && !break2; j++) { + pos = log2lin(lin2log(i) * intermediate[j]); + + if (pos > min) { + positions.push(lastPos); + } + + if (lastPos > max) { + break2 = true; + } + lastPos = pos; + } + } + + // Third case: We are so deep in between whole logarithmic values that + // we might as well handle the tick positions like a linear axis. For + // example 1.01, 1.02, 1.03, 1.04. + } else { + var realMin = lin2log(min), + realMax = lin2log(max), + tickIntervalOption = options[minor ? 'minorTickInterval' : 'tickInterval'], + filteredTickIntervalOption = tickIntervalOption === 'auto' ? null : tickIntervalOption, + tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1), + totalPixelLength = minor ? axisLength / axis.tickPositions.length : axisLength; + + interval = pick( + filteredTickIntervalOption, + axis._minorAutoInterval, + (realMax - realMin) * tickPixelIntervalOption / (totalPixelLength || 1) + ); + + interval = normalizeTickInterval( + interval, + null, + math.pow(10, mathFloor(math.log(interval) / math.LN10)) + ); + + positions = map(axis.getLinearTickPositions( + interval, + realMin, + realMax + ), log2lin); + + if (!minor) { + axis._minorAutoInterval = interval / 5; + } + } + + // Set the axis-level tickInterval variable + if (!minor) { + axis.tickInterval = interval; + } + return positions; + }, + + /** + * Return the minor tick positions. For logarithmic axes, reuse the same logic + * as for major ticks. + */ + getMinorTickPositions: function () { + var axis = this, + tickPositions = axis.tickPositions, + minorTickInterval = axis.minorTickInterval; + + var minorTickPositions = [], + pos, + i, + len; + + if (axis.isLog) { + len = tickPositions.length; + for (i = 1; i < len; i++) { + minorTickPositions = minorTickPositions.concat( + axis.getLogTickPositions(minorTickInterval, tickPositions[i - 1], tickPositions[i], true) + ); + } + + } else { + for (pos = axis.min + (tickPositions[0] - axis.min) % minorTickInterval; pos <= axis.max; pos += minorTickInterval) { + minorTickPositions.push(pos); + } + } + + return minorTickPositions; + }, + + /** + * Adjust the min and max for the minimum range. Keep in mind that the series data is + * not yet processed, so we don't have information on data cropping and grouping, or + * updated axis.pointRange or series.pointRange. The data can't be processed until + * we have finally established min and max. + */ + adjustForMinRange: function () { + var axis = this, + options = axis.options, + min = axis.min, + max = axis.max, + zoomOffset, + spaceAvailable = axis.dataMax - axis.dataMin >= axis.minRange, + closestDataRange, + i, + distance, + xData, + loopLength, + minArgs, + maxArgs; + + // Set the automatic minimum range based on the closest point distance + if (axis.isXAxis && axis.minRange === UNDEFINED && !axis.isLog) { + + if (defined(options.min) || defined(options.max)) { + axis.minRange = null; // don't do this again + + } else { + + // Find the closest distance between raw data points, as opposed to + // closestPointRange that applies to processed points (cropped and grouped) + each(axis.series, function (series) { + xData = series.xData; + loopLength = series.xIncrement ? 1 : xData.length - 1; + for (i = loopLength; i > 0; i--) { + distance = xData[i] - xData[i - 1]; + if (closestDataRange === UNDEFINED || distance < closestDataRange) { + closestDataRange = distance; + } + } + }); + axis.minRange = mathMin(closestDataRange * 5, axis.dataMax - axis.dataMin); + } + } + + // if minRange is exceeded, adjust + if (max - min < axis.minRange) { + var minRange = axis.minRange; + zoomOffset = (minRange - max + min) / 2; + + // if min and max options have been set, don't go beyond it + minArgs = [min - zoomOffset, pick(options.min, min - zoomOffset)]; + if (spaceAvailable) { // if space is available, stay within the data range + minArgs[2] = axis.dataMin; + } + min = arrayMax(minArgs); + + maxArgs = [min + minRange, pick(options.max, min + minRange)]; + if (spaceAvailable) { // if space is availabe, stay within the data range + maxArgs[2] = axis.dataMax; + } + + max = arrayMin(maxArgs); + + // now if the max is adjusted, adjust the min back + if (max - min < minRange) { + minArgs[0] = max - minRange; + minArgs[1] = pick(options.min, max - minRange); + min = arrayMax(minArgs); + } + } + + // Record modified extremes + axis.min = min; + axis.max = max; + }, + + /** + * Update translation information + */ + setAxisTranslation: function () { + var axis = this, + range = axis.max - axis.min, + pointRange = 0, + closestPointRange, + seriesClosestPointRange, + transA = axis.transA; + + // adjust translation for padding + if (axis.isXAxis) { + if (axis.isLinked) { + pointRange = axis.linkedParent.pointRange; + } else { + each(axis.series, function (series) { + pointRange = mathMax(pointRange, series.pointRange); + seriesClosestPointRange = series.closestPointRange; + if (!series.noSharedTooltip && defined(seriesClosestPointRange)) { + closestPointRange = defined(closestPointRange) ? + mathMin(closestPointRange, seriesClosestPointRange) : + seriesClosestPointRange; + } + }); + } + + // pointRange means the width reserved for each point, like in a column chart + axis.pointRange = pointRange; + + // closestPointRange means the closest distance between points. In columns + // it is mostly equal to pointRange, but in lines pointRange is 0 while closestPointRange + // is some other value + axis.closestPointRange = closestPointRange; + } + + // secondary values + axis.oldTransA = transA; + axis.translationSlope = axis.transA = transA = axis.len / ((range + pointRange) || 1); + axis.transB = axis.horiz ? axis.left : axis.bottom; // translation addend + axis.minPixelPadding = transA * (pointRange / 2); + }, + + /** + * Set the tick positions to round values and optionally extend the extremes + * to the nearest tick + */ + setTickPositions: function (secondPass) { + var axis = this, + chart = axis.chart, + options = axis.options, + isLog = axis.isLog, + isDatetimeAxis = axis.isDatetimeAxis, + isXAxis = axis.isXAxis, + isLinked = axis.isLinked, + tickPositioner = axis.options.tickPositioner, + magnitude, + maxPadding = options.maxPadding, + minPadding = options.minPadding, + length, + linkedParentExtremes, + tickIntervalOption = options.tickInterval, + tickPixelIntervalOption = options.tickPixelInterval, + tickPositions, + categories = axis.categories; + + // linked axis gets the extremes from the parent axis + if (isLinked) { + axis.linkedParent = chart[isXAxis ? 'xAxis' : 'yAxis'][options.linkedTo]; + linkedParentExtremes = axis.linkedParent.getExtremes(); + axis.min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin); + axis.max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax); + if (options.type !== axis.linkedParent.options.type) { + error(11, 1); // Can't link axes of different type + } + } else { // initial min and max from the extreme data values + axis.min = pick(axis.userMin, options.min, axis.dataMin); + axis.max = pick(axis.userMax, options.max, axis.dataMax); + } + + if (isLog) { + if (!secondPass && mathMin(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978 + error(10, 1); // Can't plot negative values on log axis + } + axis.min = correctFloat(log2lin(axis.min)); // correctFloat cures #934 + axis.max = correctFloat(log2lin(axis.max)); + } + + // handle zoomed range + if (axis.range) { + axis.userMin = axis.min = mathMax(axis.min, axis.max - axis.range); // #618 + axis.userMax = axis.max; + if (secondPass) { + axis.range = null; // don't use it when running setExtremes + } + } + + // adjust min and max for the minimum range + axis.adjustForMinRange(); + + // pad the values to get clear of the chart's edges + if (!categories && !axis.usePercentage && !isLinked && defined(axis.min) && defined(axis.max)) { + length = (axis.max - axis.min) || 1; + if (!defined(options.min) && !defined(axis.userMin) && minPadding && (axis.dataMin < 0 || !axis.ignoreMinPadding)) { + axis.min -= length * minPadding; + } + if (!defined(options.max) && !defined(axis.userMax) && maxPadding && (axis.dataMax > 0 || !axis.ignoreMaxPadding)) { + axis.max += length * maxPadding; + } + } + + // get tickInterval + if (axis.min === axis.max || axis.min === undefined || axis.max === undefined) { + axis.tickInterval = 1; + } else if (isLinked && !tickIntervalOption && + tickPixelIntervalOption === axis.linkedParent.options.tickPixelInterval) { + axis.tickInterval = axis.linkedParent.tickInterval; + } else { + axis.tickInterval = pick( + tickIntervalOption, + categories ? // for categoried axis, 1 is default, for linear axis use tickPix + 1 : + (axis.max - axis.min) * tickPixelIntervalOption / (axis.len || 1) + ); + } + + // Now we're finished detecting min and max, crop and group series data. This + // is in turn needed in order to find tick positions in ordinal axes. + if (isXAxis && !secondPass) { + each(axis.series, function (series) { + series.processData(axis.min !== axis.oldMin || axis.max !== axis.oldMax); + }); + } + + // set the translation factor used in translate function + axis.setAxisTranslation(); + + // hook for ordinal axes. To do: merge with below + if (axis.beforeSetTickPositions) { + axis.beforeSetTickPositions(); + } + + // hook for extensions, used in Highstock ordinal axes + if (axis.postProcessTickInterval) { + axis.tickInterval = axis.postProcessTickInterval(axis.tickInterval); + } + + // for linear axes, get magnitude and normalize the interval + if (!isDatetimeAxis && !isLog) { // linear + magnitude = math.pow(10, mathFloor(math.log(axis.tickInterval) / math.LN10)); + if (!defined(options.tickInterval)) { + axis.tickInterval = normalizeTickInterval(axis.tickInterval, null, magnitude, options); + } + } + + // get minorTickInterval + axis.minorTickInterval = options.minorTickInterval === 'auto' && axis.tickInterval ? + axis.tickInterval / 5 : options.minorTickInterval; + + // find the tick positions + axis.tickPositions = tickPositions = options.tickPositions || (tickPositioner && tickPositioner.apply(axis, [axis.min, axis.max])); + if (!tickPositions) { + if (isDatetimeAxis) { + tickPositions = (axis.getNonLinearTimeTicks || getTimeTicks)( + normalizeTimeTickInterval(axis.tickInterval, options.units), + axis.min, + axis.max, + options.startOfWeek, + axis.ordinalPositions, + axis.closestPointRange, + true + ); + } else if (isLog) { + tickPositions = axis.getLogTickPositions(axis.tickInterval, axis.min, axis.max); + } else { + tickPositions = axis.getLinearTickPositions(axis.tickInterval, axis.min, axis.max); + } + axis.tickPositions = tickPositions; + } + + if (!isLinked) { + + // reset min/max or remove extremes based on start/end on tick + var roundedMin = tickPositions[0], + roundedMax = tickPositions[tickPositions.length - 1]; + + if (options.startOnTick) { + axis.min = roundedMin; + } else if (axis.min > roundedMin) { + tickPositions.shift(); + } + + if (options.endOnTick) { + axis.max = roundedMax; + } else if (axis.max < roundedMax) { + tickPositions.pop(); + } + + } + }, + + /** + * Set the max ticks of either the x and y axis collection + */ + setMaxTicks: function () { + + var chart = this.chart, + maxTicks = chart.maxTicks, + tickPositions = this.tickPositions, + xOrY = this.xOrY; + + if (!maxTicks) { // first call, or maxTicks have been reset after a zoom operation + maxTicks = { + x: 0, + y: 0 + }; + } + + if (!this.isLinked && !this.isDatetimeAxis && tickPositions.length > maxTicks[xOrY] && this.options.alignTicks !== false) { + maxTicks[xOrY] = tickPositions.length; + } + chart.maxTicks = maxTicks; + }, + + /** + * When using multiple axes, adjust the number of ticks to match the highest + * number of ticks in that group + */ + adjustTickAmount: function () { + var axis = this, + chart = axis.chart, + xOrY = axis.xOrY, + tickPositions = axis.tickPositions, + maxTicks = chart.maxTicks; + + if (maxTicks && maxTicks[xOrY] && !axis.isDatetimeAxis && !axis.categories && !axis.isLinked && axis.options.alignTicks !== false) { // only apply to linear scale + var oldTickAmount = axis.tickAmount, + calculatedTickAmount = tickPositions.length, + tickAmount; + + // set the axis-level tickAmount to use below + axis.tickAmount = tickAmount = maxTicks[xOrY]; + + if (calculatedTickAmount < tickAmount) { + while (tickPositions.length < tickAmount) { + tickPositions.push(correctFloat( + tickPositions[tickPositions.length - 1] + axis.tickInterval + )); + } + axis.transA *= (calculatedTickAmount - 1) / (tickAmount - 1); + axis.max = tickPositions[tickPositions.length - 1]; + + } + if (defined(oldTickAmount) && tickAmount !== oldTickAmount) { + axis.isDirty = true; + } + } + }, + + /** + * Set the scale based on data min and max, user set min and max or options + * + */ + setScale: function () { + var axis = this, + stacks = axis.stacks, + type, + i, + isDirtyData, + isDirtyAxisLength; + + axis.oldMin = axis.min; + axis.oldMax = axis.max; + axis.oldAxisLength = axis.len; + + // set the new axisLength + axis.setAxisSize(); + //axisLength = horiz ? axisWidth : axisHeight; + isDirtyAxisLength = axis.len !== axis.oldAxisLength; + + // is there new data? + each(axis.series, function (series) { + if (series.isDirtyData || series.isDirty || + series.xAxis.isDirty) { // when x axis is dirty, we need new data extremes for y as well + isDirtyData = true; + } + }); + + // do we really need to go through all this? + if (isDirtyAxisLength || isDirtyData || axis.isLinked || + axis.userMin !== axis.oldUserMin || axis.userMax !== axis.oldUserMax) { + + // get data extremes if needed + axis.getSeriesExtremes(); + + // get fixed positions based on tickInterval + axis.setTickPositions(); + + // record old values to decide whether a rescale is necessary later on (#540) + axis.oldUserMin = axis.userMin; + axis.oldUserMax = axis.userMax; + + // Mark as dirty if it is not already set to dirty and extremes have changed. #595. + if (!axis.isDirty) { + axis.isDirty = isDirtyAxisLength || axis.min !== axis.oldMin || axis.max !== axis.oldMax; + } + } + + + // reset stacks + if (!axis.isXAxis) { + for (type in stacks) { + for (i in stacks[type]) { + stacks[type][i].cum = stacks[type][i].total; + } + } + } + + // Set the maximum tick amount + axis.setMaxTicks(); + }, + + /** + * Set the extremes and optionally redraw + * @param {Number} newMin + * @param {Number} newMax + * @param {Boolean} redraw + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + * @param {Object} eventArguments + * + */ + setExtremes: function (newMin, newMax, redraw, animation, eventArguments) { + var axis = this, + chart = axis.chart; + + redraw = pick(redraw, true); // defaults to true + + // Extend the arguments with min and max + eventArguments = extend(eventArguments, { + min: newMin, + max: newMax + }); + + // Fire the event + fireEvent(axis, 'setExtremes', eventArguments, function () { // the default event handler + + axis.userMin = newMin; + axis.userMax = newMax; + + // Mark for running afterSetExtremes + axis.isDirtyExtremes = true; + + // redraw + if (redraw) { + chart.redraw(animation); + } + }); + }, + + /** + * Update the axis metrics + */ + setAxisSize: function () { + var axis = this, + chart = axis.chart, + options = axis.options; + + var offsetLeft = options.offsetLeft || 0, + offsetRight = options.offsetRight || 0; + + // basic values + // expose to use in Series object and navigator + axis.left = pick(options.left, chart.plotLeft + offsetLeft); + axis.top = pick(options.top, chart.plotTop); + axis.width = pick(options.width, chart.plotWidth - offsetLeft + offsetRight); + axis.height = pick(options.height, chart.plotHeight); + axis.bottom = chart.chartHeight - axis.height - axis.top; + axis.right = chart.chartWidth - axis.width - axis.left; + axis.len = mathMax(axis.horiz ? axis.width : axis.height, 0); // mathMax fixes #905 + }, + + /** + * Get the actual axis extremes + */ + getExtremes: function () { + var axis = this, + isLog = axis.isLog; + + return { + min: isLog ? correctFloat(lin2log(axis.min)) : axis.min, + max: isLog ? correctFloat(lin2log(axis.max)) : axis.max, + dataMin: axis.dataMin, + dataMax: axis.dataMax, + userMin: axis.userMin, + userMax: axis.userMax + }; + }, + + /** + * Get the zero plane either based on zero or on the min or max value. + * Used in bar and area plots + */ + getThreshold: function (threshold) { + var axis = this, + isLog = axis.isLog; + + var realMin = isLog ? lin2log(axis.min) : axis.min, + realMax = isLog ? lin2log(axis.max) : axis.max; + + if (realMin > threshold || threshold === null) { + threshold = realMin; + } else if (realMax < threshold) { + threshold = realMax; + } + + return axis.translate(threshold, 0, 1, 0, 1); + }, + + /** + * Add a plot band or plot line after render time + * + * @param options {Object} The plotBand or plotLine configuration object + */ + addPlotBandOrLine: function (options) { + var obj = new PlotLineOrBand(this, options).render(); + this.plotLinesAndBands.push(obj); + return obj; + }, + + /** + * Render the tick labels to a preliminary position to get their sizes + */ + getOffset: function () { + var axis = this, + chart = axis.chart, + renderer = chart.renderer, + options = axis.options, + tickPositions = axis.tickPositions, + ticks = axis.ticks, + horiz = axis.horiz, + side = axis.side, + hasData, + showAxis, + titleOffset = 0, + titleOffsetOption, + titleMargin = 0, + axisTitleOptions = options.title, + labelOptions = options.labels, + labelOffset = 0, // reset + axisOffset = chart.axisOffset, + directionFactor = [-1, 1, 1, -1][side], + n; + + + // For reuse in Axis.render + axis.hasData = hasData = axis.series.length && defined(axis.min) && defined(axis.max); + axis.showAxis = showAxis = hasData || pick(options.showEmpty, true); + + // Create the axisGroup and gridGroup elements on first iteration + if (!axis.axisGroup) { + axis.axisGroup = renderer.g('axis') + .attr({ zIndex: options.zIndex || 7 }) + .add(); + axis.gridGroup = renderer.g('grid') + .attr({ zIndex: options.gridZIndex || 1 }) + .add(); + } + + if (hasData || axis.isLinked) { + each(tickPositions, function (pos) { + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } else { + ticks[pos].addLabel(); // update labels depending on tick interval + } + + }); + + each(tickPositions, function (pos) { + // left side must be align: right and right side must have align: left for labels + if (side === 0 || side === 2 || { 1: 'left', 3: 'right' }[side] === labelOptions.align) { + + // get the highest offset + labelOffset = mathMax( + ticks[pos].getLabelSize(), + labelOffset + ); + } + + }); + + if (axis.staggerLines) { + labelOffset += (axis.staggerLines - 1) * 16; + } + + } else { // doesn't have data + for (n in ticks) { + ticks[n].destroy(); + delete ticks[n]; + } + } + + if (axisTitleOptions && axisTitleOptions.text) { + if (!axis.axisTitle) { + axis.axisTitle = renderer.text( + axisTitleOptions.text, + 0, + 0, + axisTitleOptions.useHTML + ) + .attr({ + zIndex: 7, + rotation: axisTitleOptions.rotation || 0, + align: axisTitleOptions.textAlign || + { low: 'left', middle: 'center', high: 'right' }[axisTitleOptions.align] + }) + .css(axisTitleOptions.style) + .add(axis.axisGroup); + axis.axisTitle.isNew = true; + } + + if (showAxis) { + titleOffset = axis.axisTitle.getBBox()[horiz ? 'height' : 'width']; + titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10); + titleOffsetOption = axisTitleOptions.offset; + } + + // hide or show the title depending on whether showEmpty is set + axis.axisTitle[showAxis ? 'show' : 'hide'](); + } + + // handle automatic or user set offset + axis.offset = directionFactor * pick(options.offset, axisOffset[side]); + + + axis.axisTitleMargin = + pick(titleOffsetOption, + labelOffset + titleMargin + + (side !== 2 && labelOffset && directionFactor * options.labels[horiz ? 'y' : 'x']) + ); + + axisOffset[side] = mathMax( + axisOffset[side], + axis.axisTitleMargin + titleOffset + directionFactor * axis.offset + ); + + }, + + /** + * Get the path for the axis line + */ + getLinePath: function (lineWidth) { + var chart = this.chart, + opposite = this.opposite, + offset = this.offset, + horiz = this.horiz, + lineLeft = this.left + (opposite ? this.width : 0) + offset, + lineTop = chart.chartHeight - this.bottom - (opposite ? this.height : 0) + offset; + + return chart.renderer.crispLine([ + M, + horiz ? + this.left : + lineLeft, + horiz ? + lineTop : + this.top, + L, + horiz ? + chart.chartWidth - this.right : + lineLeft, + horiz ? + lineTop : + chart.chartHeight - this.bottom + ], lineWidth); + }, + + /** + * Position the title + */ + getTitlePosition: function () { + // compute anchor points for each of the title align options + var horiz = this.horiz, + axisLeft = this.left, + axisTop = this.top, + axisLength = this.len, + axisTitleOptions = this.options.title, + margin = horiz ? axisLeft : axisTop, + opposite = this.opposite, + offset = this.offset, + fontSize = pInt(axisTitleOptions.style.fontSize || 12), + + // the position in the length direction of the axis + alongAxis = { + low: margin + (horiz ? 0 : axisLength), + middle: margin + axisLength / 2, + high: margin + (horiz ? axisLength : 0) + }[axisTitleOptions.align], + + // the position in the perpendicular direction of the axis + offAxis = (horiz ? axisTop + this.height : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + this.axisTitleMargin + + (this.side === 2 ? fontSize : 0); + + return { + x: horiz ? + alongAxis : + offAxis + (opposite ? this.width : 0) + offset + + (axisTitleOptions.x || 0), // x + y: horiz ? + offAxis - (opposite ? this.height : 0) + offset : + alongAxis + (axisTitleOptions.y || 0) // y + }; + }, + + /** + * Render the axis + */ + render: function () { + var axis = this, + chart = axis.chart, + renderer = chart.renderer, + options = axis.options, + isLog = axis.isLog, + isLinked = axis.isLinked, + tickPositions = axis.tickPositions, + axisTitle = axis.axisTitle, + stacks = axis.stacks, + ticks = axis.ticks, + minorTicks = axis.minorTicks, + alternateBands = axis.alternateBands, + stackLabelOptions = options.stackLabels, + alternateGridColor = options.alternateGridColor, + lineWidth = options.lineWidth, + linePath, + hasRendered = chart.hasRendered, + slideInTicks = hasRendered && defined(axis.oldMin) && !isNaN(axis.oldMin), + hasData = axis.hasData, + showAxis = axis.showAxis, + from, + to; + + // If the series has data draw the ticks. Else only the line and title + if (hasData || isLinked) { + + // minor ticks + if (axis.minorTickInterval && !axis.categories) { + each(axis.getMinorTickPositions(), function (pos) { + if (!minorTicks[pos]) { + minorTicks[pos] = new Tick(axis, pos, 'minor'); + } + + // render new ticks in old position + if (slideInTicks && minorTicks[pos].isNew) { + minorTicks[pos].render(null, true); + } + + + minorTicks[pos].isActive = true; + minorTicks[pos].render(); + }); + } + + // Major ticks. Pull out the first item and render it last so that + // we can get the position of the neighbour label. #808. + each(tickPositions.slice(1).concat([tickPositions[0]]), function (pos, i) { + + // Reorganize the indices + i = (i === tickPositions.length - 1) ? 0 : i + 1; + + // linked axes need an extra check to find out if + if (!isLinked || (pos >= axis.min && pos <= axis.max)) { + + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } + + // render new ticks in old position + if (slideInTicks && ticks[pos].isNew) { + ticks[pos].render(i, true); + } + + ticks[pos].isActive = true; + ticks[pos].render(i); + } + + }); + + // alternate grid color + if (alternateGridColor) { + each(tickPositions, function (pos, i) { + if (i % 2 === 0 && pos < axis.max) { + if (!alternateBands[pos]) { + alternateBands[pos] = new PlotLineOrBand(axis); + } + from = pos; + to = tickPositions[i + 1] !== UNDEFINED ? tickPositions[i + 1] : axis.max; + alternateBands[pos].options = { + from: isLog ? lin2log(from) : from, + to: isLog ? lin2log(to) : to, + color: alternateGridColor + }; + alternateBands[pos].render(); + alternateBands[pos].isActive = true; + } + }); + } + + // custom plot lines and bands + if (!axis._addedPlotLB) { // only first time + each((options.plotLines || []).concat(options.plotBands || []), function (plotLineOptions) { + //plotLinesAndBands.push(new PlotLineOrBand(plotLineOptions).render()); + axis.addPlotBandOrLine(plotLineOptions); + }); + axis._addedPlotLB = true; + } + + } // end if hasData + + // remove inactive ticks + each([ticks, minorTicks, alternateBands], function (coll) { + var pos; + for (pos in coll) { + if (!coll[pos].isActive) { + coll[pos].destroy(); + delete coll[pos]; + } else { + coll[pos].isActive = false; // reset + } + } + }); + + // Static items. As the axis group is cleared on subsequent calls + // to render, these items are added outside the group. + // axis line + if (lineWidth) { + linePath = axis.getLinePath(lineWidth); + if (!axis.axisLine) { + axis.axisLine = renderer.path(linePath) + .attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth, + zIndex: 7 + }) + .add(); + } else { + axis.axisLine.animate({ d: linePath }); + } + + // show or hide the line depending on options.showEmpty + axis.axisLine[showAxis ? 'show' : 'hide'](); + + } + + if (axisTitle && showAxis) { + + axisTitle[axisTitle.isNew ? 'attr' : 'animate']( + axis.getTitlePosition() + ); + axisTitle.isNew = false; + } + + // Stacked totals: + if (stackLabelOptions && stackLabelOptions.enabled) { + var stackKey, oneStack, stackCategory, + stackTotalGroup = axis.stackTotalGroup; + + // Create a separate group for the stack total labels + if (!stackTotalGroup) { + axis.stackTotalGroup = stackTotalGroup = + renderer.g('stack-labels') + .attr({ + visibility: VISIBLE, + zIndex: 6 + }) + .add(); + } + + // plotLeft/Top will change when y axis gets wider so we need to translate the + // stackTotalGroup at every render call. See bug #506 and #516 + stackTotalGroup.translate(chart.plotLeft, chart.plotTop); + + // Render each stack total + for (stackKey in stacks) { + oneStack = stacks[stackKey]; + for (stackCategory in oneStack) { + oneStack[stackCategory].render(stackTotalGroup); + } + } + } + // End stacked totals + + axis.isDirty = false; + }, + + /** + * Remove a plot band or plot line from the chart by id + * @param {Object} id + */ + removePlotBandOrLine: function (id) { + var plotLinesAndBands = this.plotLinesAndBands, + i = plotLinesAndBands.length; + while (i--) { + if (plotLinesAndBands[i].id === id) { + plotLinesAndBands[i].destroy(); + } + } + }, + + /** + * Update the axis title by options + */ + setTitle: function (newTitleOptions, redraw) { + var axis = this, + chart = axis.chart, + options = axis.options, + axisTitle; + + options.title = merge(options.title, newTitleOptions); + + axis.axisTitle = axisTitle && axisTitle.destroy(); // #922 + axis.isDirty = true; + + if (pick(redraw, true)) { + chart.redraw(); + } + }, + + /** + * Redraw the axis to reflect changes in the data or axis extremes + */ + redraw: function () { + var axis = this, + chart = axis.chart; + + // hide tooltip and hover states + if (chart.tracker.resetTracker) { + chart.tracker.resetTracker(true); + } + + // render the axis + axis.render(); + + // move plot lines and bands + each(axis.plotLinesAndBands, function (plotLine) { + plotLine.render(); + }); + + // mark associated series as dirty and ready for redraw + each(axis.series, function (series) { + series.isDirty = true; + }); + + }, + + /** + * Set new axis categories and optionally redraw + * @param {Array} newCategories + * @param {Boolean} doRedraw + */ + setCategories: function (newCategories, doRedraw) { + var axis = this, + chart = axis.chart; + + // set the categories + axis.categories = axis.userOptions.categories = newCategories; + + // force reindexing tooltips + each(axis.series, function (series) { + series.translate(); + series.setTooltipPoints(true); + }); + + + // optionally redraw + axis.isDirty = true; + + if (pick(doRedraw, true)) { + chart.redraw(); + } + }, + + /** + * Destroys an Axis instance. + */ + destroy: function () { + var axis = this, + stacks = axis.stacks, + stackKey; + + // Remove the events + removeEvent(axis); + + // Destroy each stack total + for (stackKey in stacks) { + destroyObjectProperties(stacks[stackKey]); + + stacks[stackKey] = null; + } + + // Destroy collections + each([axis.ticks, axis.minorTicks, axis.alternateBands, axis.plotLinesAndBands], function (coll) { + destroyObjectProperties(coll); + }); + + // Destroy local variables + each(['stackTotalGroup', 'axisLine', 'axisGroup', 'gridGroup', 'axisTitle'], function (prop) { + if (axis[prop]) { + axis[prop] = axis[prop].destroy(); + } + }); + } + + + }; // end Axis + + /** + * The tooltip object + * @param {Object} chart The chart instance + * @param {Object} options Tooltip options + */ + function Tooltip(chart, options) { + var borderWidth = options.borderWidth, + style = options.style, + shared = options.shared, + padding = pInt(style.padding); + + // Save the chart and options + this.chart = chart; + this.options = options; + + // remove padding CSS and apply padding on box instead + style.padding = 0; + + // Keep track of the current series + //this.currentSeries = UNDEFINED; + + // List of crosshairs + this.crosshairs = []; + + // Current values of x and y when animating + this.currentX = 0; + this.currentY = 0; + + // The tooltipTick function, initialized to nothing + //this.tooltipTick = UNDEFINED; + + // The tooltip is initially hidden + this.tooltipIsHidden = true; + + // create the label + this.label = chart.renderer.label('', 0, 0, null, null, null, options.useHTML, null, 'tooltip') + .attr({ + padding: padding, + fill: options.backgroundColor, + 'stroke-width': borderWidth, + r: options.borderRadius, + zIndex: 8 + }) + .css(style) + .hide() + .add(); + + // When using canVG the shadow shows up as a gray circle + // even if the tooltip is hidden. + if (!useCanVG) { + this.label.shadow(options.shadow); + } + + // Public property for getting the shared state. + this.shared = shared; + } + + Tooltip.prototype = { + /** + * Destroy the tooltip and its elements. + */ + destroy: function () { + each(this.crosshairs, function (crosshair) { + if (crosshair) { + crosshair.destroy(); + } + }); + + // Destroy and clear local variables + if (this.label) { + this.label = this.label.destroy(); + } + }, + + /** + * Provide a soft movement for the tooltip + * + * @param {Number} finalX + * @param {Number} finalY + * @private + */ + move: function (finalX, finalY) { + var tooltip = this; + + // get intermediate values for animation + tooltip.currentX = tooltip.tooltipIsHidden ? finalX : (2 * tooltip.currentX + finalX) / 3; + tooltip.currentY = tooltip.tooltipIsHidden ? finalY : (tooltip.currentY + finalY) / 2; + + // move to the intermediate value + tooltip.label.attr({ x: tooltip.currentX, y: tooltip.currentY }); + + // run on next tick of the mouse tracker + if (mathAbs(finalX - tooltip.currentX) > 1 || mathAbs(finalY - tooltip.currentY) > 1) { + tooltip.tooltipTick = function () { + tooltip.move(finalX, finalY); + }; + } else { + tooltip.tooltipTick = null; + } + }, + + /** + * Hide the tooltip + */ + hide: function () { + if (!this.tooltipIsHidden) { + var hoverPoints = this.chart.hoverPoints; + + this.label.hide(); + + // hide previous hoverPoints and set new + if (hoverPoints) { + each(hoverPoints, function (point) { + point.setState(); + }); + } + + this.chart.hoverPoints = null; + this.tooltipIsHidden = true; + } + }, + + /** + * Hide the crosshairs + */ + hideCrosshairs: function () { + each(this.crosshairs, function (crosshair) { + if (crosshair) { + crosshair.hide(); + } + }); + }, + + /** + * Extendable method to get the anchor position of the tooltip + * from a point or set of points + */ + getAnchor: function (points, mouseEvent) { + var ret, + chart = this.chart, + inverted = chart.inverted, + plotX = 0, + plotY = 0; + + points = splat(points); + + // Pie uses a special tooltipPos + ret = points[0].tooltipPos; + + // When shared, use the average position + if (!ret) { + each(points, function (point) { + plotX += point.plotX; + plotY += point.plotLow ? (point.plotLow + point.plotHigh) / 2 : point.plotY; + }); + + plotX /= points.length; + plotY /= points.length; + + ret = [ + inverted ? chart.plotWidth - plotY : plotX, + this.shared && !inverted && points.length > 1 && mouseEvent ? + mouseEvent.chartY - chart.plotTop : // place shared tooltip next to the mouse (#424) + inverted ? chart.plotHeight - plotX : plotY + ]; + } + + return map(ret, mathRound); + }, + + /** + * Place the tooltip in a chart without spilling over + * and not covering the point it self. + */ + getPosition: function (boxWidth, boxHeight, point) { + + // Set up the variables + var chart = this.chart, + plotLeft = chart.plotLeft, + plotTop = chart.plotTop, + plotWidth = chart.plotWidth, + plotHeight = chart.plotHeight, + distance = pick(this.options.distance, 12), + pointX = point.plotX, + pointY = point.plotY, + x = pointX + plotLeft + (chart.inverted ? distance : -boxWidth - distance), + y = pointY - boxHeight + plotTop + 15, // 15 means the point is 15 pixels up from the bottom of the tooltip + alignedRight; + + // It is too far to the left, adjust it + if (x < 7) { + x = plotLeft + pointX + distance; + } + + // Test to see if the tooltip is too far to the right, + // if it is, move it back to be inside and then up to not cover the point. + if ((x + boxWidth) > (plotLeft + plotWidth)) { + x -= (x + boxWidth) - (plotLeft + plotWidth); + y = pointY - boxHeight + plotTop - distance; + alignedRight = true; + } + + // If it is now above the plot area, align it to the top of the plot area + if (y < plotTop + 5) { + y = plotTop + 5; + + // If the tooltip is still covering the point, move it below instead + if (alignedRight && pointY >= y && pointY <= (y + boxHeight)) { + y = pointY + plotTop + distance; // below + } + } + + // Now if the tooltip is below the chart, move it up. It's better to cover the + // point than to disappear outside the chart. #834. + if (y + boxHeight > plotTop + plotHeight) { + y = mathMax(plotTop, plotTop + plotHeight - boxHeight - distance); // below + } + + + return {x: x, y: y}; + }, + + /** + * Refresh the tooltip's text and position. + * @param {Object} point + */ + refresh: function (point, mouseEvent) { + var tooltip = this, + chart = tooltip.chart, + label = tooltip.label, + options = tooltip.options; + + /** + * In case no user defined formatter is given, this will be used + */ + function defaultFormatter() { + var pThis = this, + items = pThis.points || splat(pThis), + series = items[0].series, + s; + + // build the header + s = [series.tooltipHeaderFormatter(items[0].key)]; + + // build the values + each(items, function (item) { + series = item.series; + s.push((series.tooltipFormatter && series.tooltipFormatter(item)) || + item.point.tooltipFormatter(series.tooltipOptions.pointFormat)); + }); + + // footer + s.push(options.footerFormat || ''); + + return s.join(''); + } + + var x, + y, + show, + anchor, + textConfig = {}, + text, + pointConfig = [], + formatter = options.formatter || defaultFormatter, + hoverPoints = chart.hoverPoints, + placedTooltipPoint, + borderColor, + crosshairsOptions = options.crosshairs, + shared = tooltip.shared, + currentSeries; + + // get the reference point coordinates (pie charts use tooltipPos) + anchor = tooltip.getAnchor(point, mouseEvent); + x = anchor[0]; + y = anchor[1]; + + // shared tooltip, array is sent over + if (shared && !(point.series && point.series.noSharedTooltip)) { + + // hide previous hoverPoints and set new + if (hoverPoints) { + each(hoverPoints, function (point) { + point.setState(); + }); + } + chart.hoverPoints = point; + + each(point, function (item) { + item.setState(HOVER_STATE); + + pointConfig.push(item.getLabelConfig()); + }); + + textConfig = { + x: point[0].category, + y: point[0].y + }; + textConfig.points = pointConfig; + point = point[0]; + + // single point tooltip + } else { + textConfig = point.getLabelConfig(); + } + text = formatter.call(textConfig); + + // register the current series + currentSeries = point.series; + + + // For line type series, hide tooltip if the point falls outside the plot + show = shared || !currentSeries.isCartesian || currentSeries.tooltipOutsidePlot || chart.isInsidePlot(x, y); + + // update the inner HTML + if (text === false || !show) { + this.hide(); + } else { + + // show it + if (tooltip.tooltipIsHidden) { + label.show(); + } + + // update text + label.attr({ + text: text + }); + + // set the stroke color of the box + borderColor = options.borderColor || point.color || currentSeries.color || '#606060'; + label.attr({ + stroke: borderColor + }); + + placedTooltipPoint = (options.positioner || tooltip.getPosition).call( + tooltip, + label.width, + label.height, + { plotX: x, plotY: y } + ); + + // do the move + tooltip.move(mathRound(placedTooltipPoint.x), mathRound(placedTooltipPoint.y)); + + + tooltip.tooltipIsHidden = false; + } + + // crosshairs + if (crosshairsOptions) { + crosshairsOptions = splat(crosshairsOptions); // [x, y] + + var path, + i = crosshairsOptions.length, + attribs, + axis; + + while (i--) { + axis = point.series[i ? 'yAxis' : 'xAxis']; + if (crosshairsOptions[i] && axis) { + + path = axis.getPlotLinePath( + i ? pick(point.stackY, point.y) : point.x, // #814 + 1 + ); + + if (tooltip.crosshairs[i]) { + tooltip.crosshairs[i].attr({ d: path, visibility: VISIBLE }); + } else { + attribs = { + 'stroke-width': crosshairsOptions[i].width || 1, + stroke: crosshairsOptions[i].color || '#C0C0C0', + zIndex: crosshairsOptions[i].zIndex || 2 + }; + if (crosshairsOptions[i].dashStyle) { + attribs.dashstyle = crosshairsOptions[i].dashStyle; + } + tooltip.crosshairs[i] = chart.renderer.path(path) + .attr(attribs) + .add(); + } + } + } + } + fireEvent(chart, 'tooltipRefresh', { + text: text, + x: x + chart.plotLeft, + y: y + chart.plotTop, + borderColor: borderColor + }); + }, + + /** + * Runs the tooltip animation one tick. + */ + tick: function () { + if (this.tooltipTick) { + this.tooltipTick(); + } + } + }; + /** + * The mouse tracker object + * @param {Object} chart The Chart instance + * @param {Object} options The root options object + */ + function MouseTracker(chart, options) { + var zoomType = useCanVG ? '' : options.chart.zoomType; + + // Zoom status + this.zoomX = /x/.test(zoomType); + this.zoomY = /y/.test(zoomType); + + // Store reference to options + this.options = options; + + // Reference to the chart + this.chart = chart; + + // The interval id + //this.tooltipInterval = UNDEFINED; + + // The cached x hover position + //this.hoverX = UNDEFINED; + + // The chart position + //this.chartPosition = UNDEFINED; + + // The selection marker element + //this.selectionMarker = UNDEFINED; + + // False or a value > 0 if a dragging operation + //this.mouseDownX = UNDEFINED; + //this.mouseDownY = UNDEFINED; + this.init(chart, options.tooltip); + } + + MouseTracker.prototype = { + /** + * Add crossbrowser support for chartX and chartY + * @param {Object} e The event object in standard browsers + */ + normalizeMouseEvent: function (e) { + var chartPosition, + chartX, + chartY, + ePos; + + // common IE normalizing + e = e || win.event; + if (!e.target) { + e.target = e.srcElement; + } + + // jQuery only copies over some properties. IE needs e.x and iOS needs touches. + if (e.originalEvent) { + e = e.originalEvent; + } + + // The same for MooTools. It renames e.pageX to e.page.x. #445. + if (e.event) { + e = e.event; + } + + // iOS + ePos = e.touches ? e.touches.item(0) : e; + + // get mouse position + this.chartPosition = chartPosition = offset(this.chart.container); + + // chartX and chartY + if (ePos.pageX === UNDEFINED) { // IE < 9. #886. + chartX = e.x; + chartY = e.y; + } else { + chartX = ePos.pageX - chartPosition.left; + chartY = ePos.pageY - chartPosition.top; + } + + return extend(e, { + chartX: mathRound(chartX), + chartY: mathRound(chartY) + + }); + }, + + /** + * Get the click position in terms of axis values. + * + * @param {Object} e A mouse event + */ + getMouseCoordinates: function (e) { + var coordinates = { + xAxis: [], + yAxis: [] + }, + chart = this.chart; + + each(chart.axes, function (axis) { + var isXAxis = axis.isXAxis, + isHorizontal = chart.inverted ? !isXAxis : isXAxis; + + coordinates[isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: axis, + value: axis.translate( + isHorizontal ? + e.chartX - chart.plotLeft : + chart.plotHeight - e.chartY + chart.plotTop, + true + ) + }); + }); + return coordinates; + }, + + /** + * With line type charts with a single tracker, get the point closest to the mouse + */ + onmousemove: function (e) { + var mouseTracker = this, + chart = mouseTracker.chart, + series = chart.series, + point, + points, + hoverPoint = chart.hoverPoint, + hoverSeries = chart.hoverSeries, + i, + j, + distance = chart.chartWidth, + // the index in the tooltipPoints array, corresponding to pixel position in plot area + index = chart.inverted ? chart.plotHeight + chart.plotTop - e.chartY : e.chartX - chart.plotLeft; + + // shared tooltip + if (chart.tooltip && mouseTracker.options.tooltip.shared && !(hoverSeries && hoverSeries.noSharedTooltip)) { + points = []; + + // loop over all series and find the ones with points closest to the mouse + i = series.length; + for (j = 0; j < i; j++) { + if (series[j].visible && + series[j].options.enableMouseTracking !== false && !series[j].noSharedTooltip && series[j].tooltipPoints.length) { + point = series[j].tooltipPoints[index]; + point._dist = mathAbs(index - point.plotX); + distance = mathMin(distance, point._dist); + points.push(point); + } + } + // remove furthest points + i = points.length; + while (i--) { + if (points[i]._dist > distance) { + points.splice(i, 1); + } + } + // refresh the tooltip if necessary + if (points.length && (points[0].plotX !== mouseTracker.hoverX)) { + chart.tooltip.refresh(points, e); + mouseTracker.hoverX = points[0].plotX; + } + } + + // separate tooltip and general mouse events + if (hoverSeries && hoverSeries.tracker) { // only use for line-type series with common tracker + + // get the point + point = hoverSeries.tooltipPoints[index]; + + // a new point is hovered, refresh the tooltip + if (point && point !== hoverPoint) { + + // trigger the events + point.onMouseOver(); + + } + } + }, + + + /** + * Reset the tracking by hiding the tooltip, the hover series state and the hover point + */ + resetTracker: function (allowMove) { + var mouseTracker = this, + chart = mouseTracker.chart, + hoverSeries = chart.hoverSeries, + hoverPoint = chart.hoverPoint, + tooltipPoints = chart.hoverPoints || hoverPoint, + tooltip = chart.tooltip; + + // Narrow in allowMove + allowMove = allowMove && tooltip && tooltipPoints; + + // Check if the points have moved outside the plot area, #1003 + if (allowMove && splat(tooltipPoints)[0].plotX === UNDEFINED) { + allowMove = false; + } + + // Just move the tooltip, #349 + if (allowMove) { + tooltip.refresh(tooltipPoints); + + // Full reset + } else { + + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + + if (hoverSeries) { + hoverSeries.onMouseOut(); + } + + if (tooltip) { + tooltip.hide(); + tooltip.hideCrosshairs(); + } + + mouseTracker.hoverX = null; + + } + }, + + /** + * Set the JS events on the container element + */ + setDOMEvents: function () { + var lastWasOutsidePlot = true, + mouseTracker = this, + chart = mouseTracker.chart, + container = chart.container, + hasDragged, + zoomHor = (mouseTracker.zoomX && !chart.inverted) || (mouseTracker.zoomY && chart.inverted), + zoomVert = (mouseTracker.zoomY && !chart.inverted) || (mouseTracker.zoomX && chart.inverted); + + /** + * Mouse up or outside the plot area + */ + function drop() { + if (mouseTracker.selectionMarker) { + var selectionData = { + xAxis: [], + yAxis: [] + }, + selectionBox = mouseTracker.selectionMarker.getBBox(), + selectionLeft = selectionBox.x - chart.plotLeft, + selectionTop = selectionBox.y - chart.plotTop, + runZoom; + + // a selection has been made + if (hasDragged) { + + // record each axis' min and max + each(chart.axes, function (axis) { + if (axis.options.zoomEnabled !== false) { + var isXAxis = axis.isXAxis, + isHorizontal = chart.inverted ? !isXAxis : isXAxis, + selectionMin = axis.translate( + isHorizontal ? + selectionLeft : + chart.plotHeight - selectionTop - selectionBox.height, + true, + 0, + 0, + 1 + ), + selectionMax = axis.translate( + isHorizontal ? + selectionLeft + selectionBox.width : + chart.plotHeight - selectionTop, + true, + 0, + 0, + 1 + ); + + if (!isNaN(selectionMin) && !isNaN(selectionMax)) { // #859 + selectionData[isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: axis, + min: mathMin(selectionMin, selectionMax), // for reversed axes, + max: mathMax(selectionMin, selectionMax) + }); + runZoom = true; + } + } + }); + if (runZoom) { + fireEvent(chart, 'selection', selectionData, function (args) { + chart.zoom(args); + }); + } + + } + mouseTracker.selectionMarker = mouseTracker.selectionMarker.destroy(); + } + + if (chart) { // it may be destroyed on mouse up - #877 + css(container, { cursor: 'auto' }); + chart.cancelClick = hasDragged; // #370 + chart.mouseIsDown = hasDragged = false; + } + + removeEvent(doc, hasTouch ? 'touchend' : 'mouseup', drop); + } + + /** + * Special handler for mouse move that will hide the tooltip when the mouse leaves the plotarea. + */ + mouseTracker.hideTooltipOnMouseMove = function (e) { + + // Get e.pageX and e.pageY back in MooTools + washMouseEvent(e); + + // If we're outside, hide the tooltip + if (mouseTracker.chartPosition && chart.hoverSeries && chart.hoverSeries.isCartesian && !chart.isInsidePlot(e.pageX - mouseTracker.chartPosition.left - chart.plotLeft, + e.pageY - mouseTracker.chartPosition.top - chart.plotTop)) { + mouseTracker.resetTracker(); + } + }; + + /** + * When mouse leaves the container, hide the tooltip. + */ + mouseTracker.hideTooltipOnMouseLeave = function () { + mouseTracker.resetTracker(); + mouseTracker.chartPosition = null; // also reset the chart position, used in #149 fix + }; + + + /* + * Record the starting position of a dragoperation + */ + container.onmousedown = function (e) { + e = mouseTracker.normalizeMouseEvent(e); + + // issue #295, dragging not always working in Firefox + if (!hasTouch && e.preventDefault) { + e.preventDefault(); + } + + // record the start position + chart.mouseIsDown = true; + chart.cancelClick = false; + chart.mouseDownX = mouseTracker.mouseDownX = e.chartX; + mouseTracker.mouseDownY = e.chartY; + + addEvent(doc, hasTouch ? 'touchend' : 'mouseup', drop); + }; + + // The mousemove, touchmove and touchstart event handler + var mouseMove = function (e) { + // let the system handle multitouch operations like two finger scroll + // and pinching + if (e && e.touches && e.touches.length > 1) { + return; + } + + // normalize + e = mouseTracker.normalizeMouseEvent(e); + if (!hasTouch) { // not for touch devices + e.returnValue = false; + } + + var chartX = e.chartX, + chartY = e.chartY, + isOutsidePlot = !chart.isInsidePlot(chartX - chart.plotLeft, chartY - chart.plotTop); + + // on touch devices, only trigger click if a handler is defined + if (hasTouch && e.type === 'touchstart') { + if (attr(e.target, 'isTracker')) { + if (!chart.runTrackerClick) { + e.preventDefault(); + } + } else if (!chart.runChartClick && !isOutsidePlot) { + e.preventDefault(); + } + } + + // cancel on mouse outside + if (isOutsidePlot) { + + /*if (!lastWasOutsidePlot) { + // reset the tracker + resetTracker(); + }*/ + + // drop the selection if any and reset mouseIsDown and hasDragged + //drop(); + if (chartX < chart.plotLeft) { + chartX = chart.plotLeft; + } else if (chartX > chart.plotLeft + chart.plotWidth) { + chartX = chart.plotLeft + chart.plotWidth; + } + + if (chartY < chart.plotTop) { + chartY = chart.plotTop; + } else if (chartY > chart.plotTop + chart.plotHeight) { + chartY = chart.plotTop + chart.plotHeight; + } + } + + if (chart.mouseIsDown && e.type !== 'touchstart') { // make selection + + // determine if the mouse has moved more than 10px + hasDragged = Math.sqrt( + Math.pow(mouseTracker.mouseDownX - chartX, 2) + + Math.pow(mouseTracker.mouseDownY - chartY, 2) + ); + if (hasDragged > 10) { + var clickedInside = chart.isInsidePlot(mouseTracker.mouseDownX - chart.plotLeft, mouseTracker.mouseDownY - chart.plotTop); + + // make a selection + if (chart.hasCartesianSeries && (mouseTracker.zoomX || mouseTracker.zoomY) && clickedInside) { + if (!mouseTracker.selectionMarker) { + mouseTracker.selectionMarker = chart.renderer.rect( + chart.plotLeft, + chart.plotTop, + zoomHor ? 1 : chart.plotWidth, + zoomVert ? 1 : chart.plotHeight, + 0 + ) + .attr({ + fill: mouseTracker.options.chart.selectionMarkerFill || 'rgba(69,114,167,0.25)', + zIndex: 7 + }) + .add(); + } + } + + // adjust the width of the selection marker + if (mouseTracker.selectionMarker && zoomHor) { + var xSize = chartX - mouseTracker.mouseDownX; + mouseTracker.selectionMarker.attr({ + width: mathAbs(xSize), + x: (xSize > 0 ? 0 : xSize) + mouseTracker.mouseDownX + }); + } + // adjust the height of the selection marker + if (mouseTracker.selectionMarker && zoomVert) { + var ySize = chartY - mouseTracker.mouseDownY; + mouseTracker.selectionMarker.attr({ + height: mathAbs(ySize), + y: (ySize > 0 ? 0 : ySize) + mouseTracker.mouseDownY + }); + } + + // panning + if (clickedInside && !mouseTracker.selectionMarker && mouseTracker.options.chart.panning) { + chart.pan(chartX); + } + } + + } else if (!isOutsidePlot) { + // show the tooltip + mouseTracker.onmousemove(e); + } + + lastWasOutsidePlot = isOutsidePlot; + + // when outside plot, allow touch-drag by returning true + return isOutsidePlot || !chart.hasCartesianSeries; + }; + + /* + * When the mouse enters the container, run mouseMove + */ + container.onmousemove = mouseMove; + + /* + * When the mouse leaves the container, hide the tracking (tooltip). + */ + addEvent(container, 'mouseleave', mouseTracker.hideTooltipOnMouseLeave); + + // issue #149 workaround + // The mouseleave event above does not always fire. Whenever the mouse is moving + // outside the plotarea, hide the tooltip + addEvent(doc, 'mousemove', mouseTracker.hideTooltipOnMouseMove); + + container.ontouchstart = function (e) { + // For touch devices, use touchmove to zoom + if (mouseTracker.zoomX || mouseTracker.zoomY) { + container.onmousedown(e); + } + // Show tooltip and prevent the lower mouse pseudo event + mouseMove(e); + }; + + /* + * Allow dragging the finger over the chart to read the values on touch + * devices + */ + container.ontouchmove = mouseMove; + + /* + * Allow dragging the finger over the chart to read the values on touch + * devices + */ + container.ontouchend = function () { + if (hasDragged) { + mouseTracker.resetTracker(); + } + }; + + + // MooTools 1.2.3 doesn't fire this in IE when using addEvent + container.onclick = function (e) { + var hoverPoint = chart.hoverPoint, + plotX, + plotY; + e = mouseTracker.normalizeMouseEvent(e); + + e.cancelBubble = true; // IE specific + + + if (!chart.cancelClick) { + // Detect clicks on trackers or tracker groups, #783 + if (hoverPoint && (attr(e.target, 'isTracker') || attr(e.target.parentNode, 'isTracker'))) { + plotX = hoverPoint.plotX; + plotY = hoverPoint.plotY; + + // add page position info + extend(hoverPoint, { + pageX: mouseTracker.chartPosition.left + chart.plotLeft + + (chart.inverted ? chart.plotWidth - plotY : plotX), + pageY: mouseTracker.chartPosition.top + chart.plotTop + + (chart.inverted ? chart.plotHeight - plotX : plotY) + }); + + // the series click event + fireEvent(hoverPoint.series, 'click', extend(e, { + point: hoverPoint + })); + + // the point click event + hoverPoint.firePointEvent('click', e); + + } else { + extend(e, mouseTracker.getMouseCoordinates(e)); + + // fire a click event in the chart + if (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + fireEvent(chart, 'click', e); + } + } + + + } + }; + + }, + + /** + * Destroys the MouseTracker object and disconnects DOM events. + */ + destroy: function () { + var mouseTracker = this, + chart = mouseTracker.chart, + container = chart.container; + + // Destroy the tracker group element + if (chart.trackerGroup) { + chart.trackerGroup = chart.trackerGroup.destroy(); + } + + removeEvent(container, 'mouseleave', mouseTracker.hideTooltipOnMouseLeave); + removeEvent(doc, 'mousemove', mouseTracker.hideTooltipOnMouseMove); + container.onclick = container.onmousedown = container.onmousemove = container.ontouchstart = container.ontouchend = container.ontouchmove = null; + + // memory and CPU leak + clearInterval(this.tooltipInterval); + }, + + // Run MouseTracker + init: function (chart, options) { + if (!chart.trackerGroup) { + chart.trackerGroup = chart.renderer.g('tracker') + .attr({ zIndex: 9 }) + .add(); + } + + if (options.enabled) { + chart.tooltip = new Tooltip(chart, options); + + // set the fixed interval ticking for the smooth tooltip + this.tooltipInterval = setInterval(function () { + chart.tooltip.tick(); + }, 32); + } + + this.setDOMEvents(); + } + }; + /** + * The overview of the chart's series + */ + function Legend(chart) { + + this.init(chart); + } + + Legend.prototype = { + + /** + * Initialize the legend + */ + init: function (chart) { + var legend = this, + options = legend.options = chart.options.legend; + + if (!options.enabled) { + return; + } + + var //style = options.style || {}, // deprecated + itemStyle = options.itemStyle, + padding = pick(options.padding, 8), + itemMarginTop = options.itemMarginTop || 0; + + legend.baseline = pInt(itemStyle.fontSize) + 3 + itemMarginTop; // used in Series prototype + legend.itemStyle = itemStyle; + legend.itemHiddenStyle = merge(itemStyle, options.itemHiddenStyle); + legend.itemMarginTop = itemMarginTop; + legend.padding = padding; + legend.initialItemX = padding; + legend.initialItemY = padding - 5; // 5 is the number of pixels above the text + legend.maxItemWidth = 0; + legend.chart = chart; + //legend.allItems = UNDEFINED; + //legend.legendWidth = UNDEFINED; + //legend.legendHeight = UNDEFINED; + //legend.offsetWidth = UNDEFINED; + legend.itemHeight = 0; + legend.lastLineHeight = 0; + //legend.itemX = UNDEFINED; + //legend.itemY = UNDEFINED; + //legend.lastItemY = UNDEFINED; + + // Elements + //legend.group = UNDEFINED; + //legend.box = UNDEFINED; + + // run legend + legend.render(); + + // move checkboxes + addEvent(legend.chart, 'endResize', function () { + legend.positionCheckboxes(); + }); + + /* // expose + return { + colorizeItem: colorizeItem, + destroyItem: destroyItem, + render: render, + destroy: destroy, + getLegendWidth: getLegendWidth, + getLegendHeight: getLegendHeight + };*/ + }, + + /** + * Set the colors for the legend item + * @param {Object} item A Series or Point instance + * @param {Object} visible Dimmed or colored + */ + colorizeItem: function (item, visible) { + var legend = this, + options = legend.options, + legendItem = item.legendItem, + legendLine = item.legendLine, + legendSymbol = item.legendSymbol, + hiddenColor = legend.itemHiddenStyle.color, + textColor = visible ? options.itemStyle.color : hiddenColor, + symbolColor = visible ? item.color : hiddenColor; + + if (legendItem) { + legendItem.css({ fill: textColor }); + } + if (legendLine) { + legendLine.attr({ stroke: symbolColor }); + } + if (legendSymbol) { + legendSymbol.attr({ + stroke: symbolColor, + fill: symbolColor + }); + } + }, + + /** + * Position the legend item + * @param {Object} item A Series or Point instance + */ + positionItem: function (item) { + var legend = this, + options = legend.options, + symbolPadding = options.symbolPadding, + ltr = !options.rtl, + legendItemPos = item._legendItemPos, + itemX = legendItemPos[0], + itemY = legendItemPos[1], + checkbox = item.checkbox; + + if (item.legendGroup) { + item.legendGroup.translate( + ltr ? itemX : legend.legendWidth - itemX - 2 * symbolPadding - 4, + itemY + ); + } + + if (checkbox) { + checkbox.x = itemX; + checkbox.y = itemY; + } + }, + + /** + * Destroy a single legend item + * @param {Object} item The series or point + */ + destroyItem: function (item) { + var checkbox = item.checkbox; + + // destroy SVG elements + each(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function (key) { + if (item[key]) { + item[key].destroy(); + } + }); + + if (checkbox) { + discardElement(item.checkbox); + } + }, + + /** + * Destroys the legend. + */ + destroy: function () { + var legend = this, + legendGroup = legend.group, + box = legend.box; + + if (box) { + legend.box = box.destroy(); + } + + if (legendGroup) { + legend.group = legendGroup.destroy(); + } + }, + + /** + * Position the checkboxes after the width is determined + */ + positionCheckboxes: function () { + var legend = this; + + each(legend.allItems, function (item) { + var checkbox = item.checkbox, + alignAttr = legend.group.alignAttr; + if (checkbox) { + css(checkbox, { + left: (alignAttr.translateX + item.legendItemWidth + checkbox.x - 20) + PX, + top: (alignAttr.translateY + checkbox.y + 3) + PX + }); + } + }); + }, + + /** + * Render a single specific legend item + * @param {Object} item A series or point + */ + renderItem: function (item) { + var legend = this, + chart = legend.chart, + renderer = chart.renderer, + options = legend.options, + horizontal = options.layout === 'horizontal', + symbolWidth = options.symbolWidth, + symbolPadding = options.symbolPadding, + itemStyle = legend.itemStyle, + itemHiddenStyle = legend.itemHiddenStyle, + padding = legend.padding, + ltr = !options.rtl, + itemHeight, + widthOption = options.width, + itemMarginBottom = options.itemMarginBottom || 0, + itemMarginTop = legend.itemMarginTop, + initialItemX = legend.initialItemX, + bBox, + itemWidth, + li = item.legendItem, + series = item.series || item, + itemOptions = series.options, + showCheckbox = itemOptions.showCheckbox; + + if (!li) { // generate it once, later move it + + // Generate the group box + // A group to hold the symbol and text. Text is to be appended in Legend class. + item.legendGroup = renderer.g('legend-item') + .attr({ zIndex: 1 }) + .add(legend.scrollGroup); + + // Draw the legend symbol inside the group box + series.drawLegendSymbol(legend, item); + + // Generate the list item text and add it to the group + item.legendItem = li = renderer.text( + options.labelFormatter.call(item), + ltr ? symbolWidth + symbolPadding : -symbolPadding, + legend.baseline, + options.useHTML + ) + .css(merge(item.visible ? itemStyle : itemHiddenStyle)) // merge to prevent modifying original (#1021) + .attr({ + align: ltr ? 'left' : 'right', + zIndex: 2 + }) + .add(item.legendGroup); + + // Set the events on the item group + item.legendGroup.on('mouseover', function () { + item.setState(HOVER_STATE); + li.css(legend.options.itemHoverStyle); + }) + .on('mouseout', function () { + li.css(item.visible ? itemStyle : itemHiddenStyle); + item.setState(); + }) + .on('click', function (event) { + var strLegendItemClick = 'legendItemClick', + fnLegendItemClick = function () { + item.setVisible(); + }; + + // Pass over the click/touch event. #4. + event = { + browserEvent: event + }; + + // click the name or symbol + if (item.firePointEvent) { // point + item.firePointEvent(strLegendItemClick, event, fnLegendItemClick); + } else { + fireEvent(item, strLegendItemClick, event, fnLegendItemClick); + } + }); + + // Colorize the items + legend.colorizeItem(item, item.visible); + + // add the HTML checkbox on top + if (itemOptions && showCheckbox) { + item.checkbox = createElement('input', { + type: 'checkbox', + checked: item.selected, + defaultChecked: item.selected // required by IE7 + }, options.itemCheckboxStyle, chart.container); + + addEvent(item.checkbox, 'click', function (event) { + var target = event.target; + fireEvent(item, 'checkboxClick', { + checked: target.checked + }, + function () { + item.select(); + } + ); + }); + } + } + + // calculate the positions for the next line + bBox = li.getBBox(); + + itemWidth = item.legendItemWidth = + options.itemWidth || symbolWidth + symbolPadding + bBox.width + padding + + (showCheckbox ? 20 : 0); + legend.itemHeight = itemHeight = bBox.height; + + // if the item exceeds the width, start a new line + if (horizontal && legend.itemX - initialItemX + itemWidth > + (widthOption || (chart.chartWidth - 2 * padding - initialItemX))) { + legend.itemX = initialItemX; + legend.itemY += itemMarginTop + legend.lastLineHeight + itemMarginBottom; + legend.lastLineHeight = 0; // reset for next line + } + + // If the item exceeds the height, start a new column + /*if (!horizontal && legend.itemY + options.y + itemHeight > chart.chartHeight - spacingTop - spacingBottom) { + legend.itemY = legend.initialItemY; + legend.itemX += legend.maxItemWidth; + legend.maxItemWidth = 0; + }*/ + + // Set the edge positions + legend.maxItemWidth = mathMax(legend.maxItemWidth, itemWidth); + legend.lastItemY = itemMarginTop + legend.itemY + itemMarginBottom; + legend.lastLineHeight = mathMax(itemHeight, legend.lastLineHeight); // #915 + + // cache the position of the newly generated or reordered items + item._legendItemPos = [legend.itemX, legend.itemY]; + + // advance + if (horizontal) { + legend.itemX += itemWidth; + + } else { + legend.itemY += itemMarginTop + itemHeight + itemMarginBottom; + legend.lastLineHeight = itemHeight; + } + + // the width of the widest item + legend.offsetWidth = widthOption || mathMax( + horizontal ? legend.itemX - initialItemX : itemWidth, + legend.offsetWidth + ); + }, + + /** + * Render the legend. This method can be called both before and after + * chart.render. If called after, it will only rearrange items instead + * of creating new ones. + */ + render: function () { + var legend = this, + chart = legend.chart, + renderer = chart.renderer, + legendGroup = legend.group, + allItems, + display, + legendWidth, + legendHeight, + box = legend.box, + options = legend.options, + padding = legend.padding, + legendBorderWidth = options.borderWidth, + legendBackgroundColor = options.backgroundColor; + + legend.itemX = legend.initialItemX; + legend.itemY = legend.initialItemY; + legend.offsetWidth = 0; + legend.lastItemY = 0; + + if (!legendGroup) { + legend.group = legendGroup = renderer.g('legend') + // #414, #759. Trackers will be drawn above the legend, but we have + // to sacrifice that because tooltips need to be above the legend + // and trackers above tooltips + .attr({ zIndex: 7 }) + .add(); + legend.contentGroup = renderer.g() + .attr({ zIndex: 1 }) // above background + .add(legendGroup); + legend.scrollGroup = renderer.g() + .add(legend.contentGroup); + legend.clipRect = renderer.clipRect(0, 0, 9999, chart.chartHeight); + legend.contentGroup.clip(legend.clipRect); + } + + // add each series or point + allItems = []; + each(chart.series, function (serie) { + var seriesOptions = serie.options; + + if (!seriesOptions.showInLegend) { + return; + } + + // use points or series for the legend item depending on legendType + allItems = allItems.concat( + serie.legendItems || + (seriesOptions.legendType === 'point' ? + serie.data : + serie) + ); + }); + + // sort by legendIndex + stableSort(allItems, function (a, b) { + return (a.options.legendIndex || 0) - (b.options.legendIndex || 0); + }); + + // reversed legend + if (options.reversed) { + allItems.reverse(); + } + + legend.allItems = allItems; + legend.display = display = !!allItems.length; + + // render the items + each(allItems, function (item) { + legend.renderItem(item); + }); + + // Draw the border + legendWidth = options.width || legend.offsetWidth; + legendHeight = legend.lastItemY + legend.lastLineHeight; + + + legendHeight = legend.handleOverflow(legendHeight); + + if (legendBorderWidth || legendBackgroundColor) { + legendWidth += padding; + legendHeight += padding; + + if (!box) { + legend.box = box = renderer.rect( + 0, + 0, + legendWidth, + legendHeight, + options.borderRadius, + legendBorderWidth || 0 + ).attr({ + stroke: options.borderColor, + 'stroke-width': legendBorderWidth || 0, + fill: legendBackgroundColor || NONE + }) + .add(legendGroup) + .shadow(options.shadow); + box.isNew = true; + + } else if (legendWidth > 0 && legendHeight > 0) { + box[box.isNew ? 'attr' : 'animate']( + box.crisp(null, null, null, legendWidth, legendHeight) + ); + box.isNew = false; + } + + // hide the border if no items + box[display ? 'show' : 'hide'](); + } + + legend.legendWidth = legendWidth; + legend.legendHeight = legendHeight; + + // Now that the legend width and height are established, put the items in the + // final position + each(allItems, function (item) { + legend.positionItem(item); + }); + + // 1.x compatibility: positioning based on style + /*var props = ['left', 'right', 'top', 'bottom'], + prop, + i = 4; + while (i--) { + prop = props[i]; + if (options.style[prop] && options.style[prop] !== 'auto') { + options[i < 2 ? 'align' : 'verticalAlign'] = prop; + options[i < 2 ? 'x' : 'y'] = pInt(options.style[prop]) * (i % 2 ? -1 : 1); + } + }*/ + + if (display) { + legendGroup.align(extend({ + width: legendWidth, + height: legendHeight + }, options), true, chart.spacingBox); + } + + if (!chart.isResizing) { + this.positionCheckboxes(); + } + }, + + /** + * Set up the overflow handling by adding navigation with up and down arrows below the + * legend. + */ + handleOverflow: function (legendHeight) { + var legend = this, + chart = this.chart, + renderer = chart.renderer, + pageCount, + options = this.options, + optionsY = options.y, + alignTop = options.verticalAlign === 'top', + spaceHeight = chart.spacingBox.height + (alignTop ? -optionsY : optionsY) - this.padding, + maxHeight = options.maxHeight, // docs + clipHeight, + clipRect = this.clipRect, + navOptions = options.navigation, + animation = pick(navOptions.animation, true), + arrowSize = navOptions.arrowSize || 12, + nav = this.nav; + + // Adjust the height + if (options.layout === 'horizontal') { + spaceHeight /= 2; + } + if (maxHeight) { + spaceHeight = mathMin(spaceHeight, maxHeight); + } + + // Reset the legend height and adjust the clipping rectangle + if (legendHeight > spaceHeight) { + + this.clipHeight = clipHeight = spaceHeight - 20; + this.pageCount = pageCount = mathCeil(legendHeight / clipHeight); + this.currentPage = pick(this.currentPage, 1); + this.fullHeight = legendHeight; + + clipRect.attr({ + height: clipHeight + }); + + // Add navigation elements + if (!nav) { + this.nav = nav = renderer.g().attr({ zIndex: 1 }).add(this.group); + this.up = renderer.symbol('triangle', 0, 0, arrowSize, arrowSize) + .on('click', function () { + legend.scroll(-1, animation); + }) + .add(nav); + this.pager = renderer.text('', 15, 10) + .css(navOptions.style) + .add(nav); + this.down = renderer.symbol('triangle-down', 0, 0, arrowSize, arrowSize) + .on('click', function () { + legend.scroll(1, animation); + }) + .add(nav); + } + + // Set initial position + legend.scroll(0); + + legendHeight = spaceHeight; + + } else if (nav) { + clipRect.attr({ + height: chart.chartHeight + }); + nav.hide(); + this.scrollGroup.attr({ + translateY: 1 + }); + } + + return legendHeight; + }, + + /** + * Scroll the legend by a number of pages + * @param {Object} scrollBy + * @param {Object} animation + */ + scroll: function (scrollBy, animation) { + var pageCount = this.pageCount, + currentPage = this.currentPage + scrollBy, + clipHeight = this.clipHeight, + navOptions = this.options.navigation, + activeColor = navOptions.activeColor, + inactiveColor = navOptions.inactiveColor, + pager = this.pager, + padding = this.padding; + + // When resizing while looking at the last page + if (currentPage > pageCount) { + currentPage = pageCount; + } + + if (currentPage > 0) { + + if (animation !== UNDEFINED) { + setAnimation(animation, this.chart); + } + + this.nav.attr({ + translateX: padding, + translateY: clipHeight + 7, + visibility: VISIBLE + }); + this.up.attr({ + fill: currentPage === 1 ? inactiveColor : activeColor + }) + .css({ + cursor: currentPage === 1 ? 'default' : 'pointer' + }); + pager.attr({ + text: currentPage + '/' + this.pageCount + }); + this.down.attr({ + x: 18 + this.pager.getBBox().width, // adjust to text width + fill: currentPage === pageCount ? inactiveColor : activeColor + }) + .css({ + cursor: currentPage === pageCount ? 'default' : 'pointer' + }); + + this.scrollGroup.animate({ + translateY: -mathMin(clipHeight * (currentPage - 1), this.fullHeight - clipHeight + padding) + 1 + }); + pager.attr({ + text: currentPage + '/' + pageCount + }); + + + this.currentPage = currentPage; + } + + } + + }; + + + /** + * The chart class + * @param {Object} options + * @param {Function} callback Function to run when the chart has loaded + */ + function Chart(userOptions, callback) { + // Handle regular options + var options, + seriesOptions = userOptions.series; // skip merging data points to increase performance + userOptions.series = null; + options = merge(defaultOptions, userOptions); // do the merge + options.series = userOptions.series = seriesOptions; // set back the series data + + var optionsChart = options.chart, + optionsMargin = optionsChart.margin, + margin = isObject(optionsMargin) ? + optionsMargin : + [optionsMargin, optionsMargin, optionsMargin, optionsMargin]; + + this.optionsMarginTop = pick(optionsChart.marginTop, margin[0]); + this.optionsMarginRight = pick(optionsChart.marginRight, margin[1]); + this.optionsMarginBottom = pick(optionsChart.marginBottom, margin[2]); + this.optionsMarginLeft = pick(optionsChart.marginLeft, margin[3]); + + var chartEvents = optionsChart.events; + + this.runChartClick = chartEvents && !!chartEvents.click; + this.callback = callback; + this.isResizing = 0; + this.options = options; + //chartTitleOptions = UNDEFINED; + //chartSubtitleOptions = UNDEFINED; + + this.axes = []; + this.series = []; + this.hasCartesianSeries = optionsChart.showAxes; + //this.axisOffset = UNDEFINED; + //this.maxTicks = UNDEFINED; // handle the greatest amount of ticks on grouped axes + //this.inverted = UNDEFINED; + //this.loadingShown = UNDEFINED; + //this.container = UNDEFINED; + //this.chartWidth = UNDEFINED; + //this.chartHeight = UNDEFINED; + //this.marginRight = UNDEFINED; + //this.marginBottom = UNDEFINED; + //this.containerWidth = UNDEFINED; + //this.containerHeight = UNDEFINED; + //this.oldChartWidth = UNDEFINED; + //this.oldChartHeight = UNDEFINED; + + //this.renderTo = UNDEFINED; + //this.renderToClone = UNDEFINED; + //this.tracker = UNDEFINED; + + //this.spacingBox = UNDEFINED + + //this.legend = UNDEFINED; + + // Elements + //this.chartBackground = UNDEFINED; + //this.plotBackground = UNDEFINED; + //this.plotBGImage = UNDEFINED; + //this.plotBorder = UNDEFINED; + //this.loadingDiv = UNDEFINED; + //this.loadingSpan = UNDEFINED; + + this.init(chartEvents); + } + + Chart.prototype = { + + /** + * Initialize an individual series, called internally before render time + */ + initSeries: function (options) { + var chart = this, + optionsChart = chart.options.chart, + type = options.type || optionsChart.type || optionsChart.defaultSeriesType, + series = new seriesTypes[type](); + + series.init(this, options); + return series; + }, + + /** + * Add a series dynamically after time + * + * @param {Object} options The config options + * @param {Boolean} redraw Whether to redraw the chart after adding. Defaults to true. + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + * + * @return {Object} series The newly created series object + */ + addSeries: function (options, redraw, animation) { + var series, + chart = this; + + if (options) { + setAnimation(animation, chart); + redraw = pick(redraw, true); // defaults to true + + fireEvent(chart, 'addSeries', { options: options }, function () { + chart.initSeries(options); + //series = chart.initSeries(options); + //series.isDirty = true; + + chart.isDirtyLegend = true; // the series array is out of sync with the display + if (redraw) { + chart.redraw(); + } + }); + } + + return series; + }, + + /** + * Check whether a given point is within the plot area + * + * @param {Number} x Pixel x relative to the plot area + * @param {Number} y Pixel y relative to the plot area + */ + isInsidePlot: function (x, y) { + return x >= 0 && + x <= this.plotWidth && + y >= 0 && + y <= this.plotHeight; + }, + + /** + * Adjust all axes tick amounts + */ + adjustTickAmounts: function () { + if (this.options.chart.alignTicks !== false) { + each(this.axes, function (axis) { + axis.adjustTickAmount(); + }); + } + this.maxTicks = null; + }, + + /** + * Redraw legend, axes or series based on updated data + * + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + */ + redraw: function (animation) { + var chart = this, + axes = chart.axes, + series = chart.series, + tracker = chart.tracker, + legend = chart.legend, + redrawLegend = chart.isDirtyLegend, + hasStackedSeries, + isDirtyBox = chart.isDirtyBox, // todo: check if it has actually changed? + seriesLength = series.length, + i = seriesLength, + clipRect = chart.clipRect, + serie, + renderer = chart.renderer, + isHiddenChart = renderer.isHidden(); + + setAnimation(animation, chart); + + if (isHiddenChart) { + chart.cloneRenderTo(); + } + + // link stacked series + while (i--) { + serie = series[i]; + if (serie.isDirty && serie.options.stacking) { + hasStackedSeries = true; + break; + } + } + if (hasStackedSeries) { // mark others as dirty + i = seriesLength; + while (i--) { + serie = series[i]; + if (serie.options.stacking) { + serie.isDirty = true; + } + } + } + + // handle updated data in the series + each(series, function (serie) { + if (serie.isDirty) { // prepare the data so axis can read it + if (serie.options.legendType === 'point') { + redrawLegend = true; + } + } + }); + + // handle added or removed series + if (redrawLegend && legend.options.enabled) { // series or pie points are added or removed + // draw legend graphics + legend.render(); + + chart.isDirtyLegend = false; + } + + + if (chart.hasCartesianSeries) { + if (!chart.isResizing) { + + // reset maxTicks + chart.maxTicks = null; + + // set axes scales + each(axes, function (axis) { + axis.setScale(); + }); + } + chart.adjustTickAmounts(); + chart.getMargins(); + + // redraw axes + each(axes, function (axis) { + + // Fire 'afterSetExtremes' only if extremes are set + if (axis.isDirtyExtremes) { // #821 + axis.isDirtyExtremes = false; + fireEvent(axis, 'afterSetExtremes', axis.getExtremes()); // #747, #751 + } + + if (axis.isDirty || isDirtyBox || hasStackedSeries) { + axis.redraw(); + isDirtyBox = true; // #792 + } + }); + + + } + + // the plot areas size has changed + if (isDirtyBox) { + chart.drawChartBox(); + + // move clip rect + if (clipRect) { + stop(clipRect); + clipRect.animate({ // for chart resize + width: chart.plotSizeX, + height: chart.plotSizeY + 1 + }); + } + + } + + + // redraw affected series + each(series, function (serie) { + if (serie.isDirty && serie.visible && + (!serie.isCartesian || serie.xAxis)) { // issue #153 + serie.redraw(); + } + }); + + + // move tooltip or reset + if (tracker && tracker.resetTracker) { + tracker.resetTracker(true); + } + + // redraw if canvas + renderer.draw(); + + // fire the event + fireEvent(chart, 'redraw'); // jQuery breaks this when calling it from addEvent. Overwrites chart.redraw + + if (isHiddenChart) { + chart.cloneRenderTo(true); + } + }, + + + /** + * Dim the chart and show a loading text or symbol + * @param {String} str An optional text to show in the loading label instead of the default one + */ + showLoading: function (str) { + var chart = this, + options = chart.options, + loadingDiv = chart.loadingDiv; + + var loadingOptions = options.loading; + + // create the layer at the first call + if (!loadingDiv) { + chart.loadingDiv = loadingDiv = createElement(DIV, { + className: PREFIX + 'loading' + }, extend(loadingOptions.style, { + left: chart.plotLeft + PX, + top: chart.plotTop + PX, + width: chart.plotWidth + PX, + height: chart.plotHeight + PX, + zIndex: 10, + display: NONE + }), chart.container); + + chart.loadingSpan = createElement( + 'span', + null, + loadingOptions.labelStyle, + loadingDiv + ); + + } + + // update text + chart.loadingSpan.innerHTML = str || options.lang.loading; + + // show it + if (!chart.loadingShown) { + css(loadingDiv, { opacity: 0, display: '' }); + animate(loadingDiv, { + opacity: loadingOptions.style.opacity + }, { + duration: loadingOptions.showDuration || 0 + }); + chart.loadingShown = true; + } + }, + + /** + * Hide the loading layer + */ + hideLoading: function () { + var options = this.options, + loadingDiv = this.loadingDiv; + + if (loadingDiv) { + animate(loadingDiv, { + opacity: 0 + }, { + duration: options.loading.hideDuration || 100, + complete: function () { + css(loadingDiv, { display: NONE }); + } + }); + } + this.loadingShown = false; + }, + + /** + * Get an axis, series or point object by id. + * @param id {String} The id as given in the configuration options + */ + get: function (id) { + var chart = this, + axes = chart.axes, + series = chart.series; + + var i, + j, + points; + + // search axes + for (i = 0; i < axes.length; i++) { + if (axes[i].options.id === id) { + return axes[i]; + } + } + + // search series + for (i = 0; i < series.length; i++) { + if (series[i].options.id === id) { + return series[i]; + } + } + + // search points + for (i = 0; i < series.length; i++) { + points = series[i].points || []; + for (j = 0; j < points.length; j++) { + if (points[j].id === id) { + return points[j]; + } + } + } + return null; + }, + + /** + * Create the Axis instances based on the config options + */ + getAxes: function () { + var chart = this, + options = this.options; + + var xAxisOptions = options.xAxis || {}, + yAxisOptions = options.yAxis || {}, + optionsArray, + axis; + + // make sure the options are arrays and add some members + xAxisOptions = splat(xAxisOptions); + each(xAxisOptions, function (axis, i) { + axis.index = i; + axis.isX = true; + }); + + yAxisOptions = splat(yAxisOptions); + each(yAxisOptions, function (axis, i) { + axis.index = i; + }); + + // concatenate all axis options into one array + optionsArray = xAxisOptions.concat(yAxisOptions); + + each(optionsArray, function (axisOptions) { + axis = new Axis(chart, axisOptions); + }); + + chart.adjustTickAmounts(); + }, + + + /** + * Get the currently selected points from all series + */ + getSelectedPoints: function () { + var points = []; + each(this.series, function (serie) { + points = points.concat(grep(serie.points, function (point) { + return point.selected; + })); + }); + return points; + }, + + /** + * Get the currently selected series + */ + getSelectedSeries: function () { + return grep(this.series, function (serie) { + return serie.selected; + }); + }, + + /** + * Display the zoom button + */ + showResetZoom: function () { + var chart = this, + lang = defaultOptions.lang, + btnOptions = chart.options.chart.resetZoomButton, + theme = btnOptions.theme, + states = theme.states, + box = btnOptions.relativeTo === 'chart' ? null : { + x: chart.plotLeft, + y: chart.plotTop, + width: chart.plotWidth, + height: chart.plotHeight + }; + this.resetZoomButton = chart.renderer.button(lang.resetZoom, null, null, function () { + chart.zoomOut(); + }, theme, states && states.hover) + .attr({ + align: btnOptions.position.align, + title: lang.resetZoomTitle + }) + .add() + .align(btnOptions.position, false, box); + }, + + /** + * Zoom out to 1:1 + */ + zoomOut: function () { + var chart = this, + resetZoomButton = chart.resetZoomButton; + + fireEvent(chart, 'selection', { resetSelection: true }, function () { + chart.zoom(); + }); + if (resetZoomButton) { + chart.resetZoomButton = resetZoomButton.destroy(); + } + }, + + /** + * Zoom into a given portion of the chart given by axis coordinates + * @param {Object} event + */ + zoom: function (event) { + var chart = this, + optionsChart = chart.options.chart; + + // add button to reset selection + var hasZoomed; + + if (chart.resetZoomEnabled !== false && !chart.resetZoomButton) { // hook for Stock charts etc. + chart.showResetZoom(); + } + + // if zoom is called with no arguments, reset the axes + if (!event || event.resetSelection) { + each(chart.axes, function (axis) { + if (axis.options.zoomEnabled !== false) { + axis.setExtremes(null, null, false); + hasZoomed = true; + } + }); + } else { // else, zoom in on all axes + each(event.xAxis.concat(event.yAxis), function (axisData) { + var axis = axisData.axis; + + // don't zoom more than minRange + if (chart.tracker[axis.isXAxis ? 'zoomX' : 'zoomY']) { + axis.setExtremes(axisData.min, axisData.max, false); + hasZoomed = true; + } + }); + } + + // Redraw + if (hasZoomed) { + chart.redraw( + pick(optionsChart.animation, chart.pointCount < 100) // animation + ); + } + }, + + /** + * Pan the chart by dragging the mouse across the pane. This function is called + * on mouse move, and the distance to pan is computed from chartX compared to + * the first chartX position in the dragging operation. + */ + pan: function (chartX) { + var chart = this; + + var xAxis = chart.xAxis[0], + mouseDownX = chart.mouseDownX, + halfPointRange = xAxis.pointRange / 2, + extremes = xAxis.getExtremes(), + newMin = xAxis.translate(mouseDownX - chartX, true) + halfPointRange, + newMax = xAxis.translate(mouseDownX + chart.plotWidth - chartX, true) - halfPointRange, + hoverPoints = chart.hoverPoints; + + // remove active points for shared tooltip + if (hoverPoints) { + each(hoverPoints, function (point) { + point.setState(); + }); + } + + if (xAxis.series.length && newMin > mathMin(extremes.dataMin, extremes.min) && newMax < mathMax(extremes.dataMax, extremes.max)) { + xAxis.setExtremes(newMin, newMax, true, false); + } + + chart.mouseDownX = chartX; // set new reference for next run + css(chart.container, { cursor: 'move' }); + }, + + /** + * Show the title and subtitle of the chart + * + * @param titleOptions {Object} New title options + * @param subtitleOptions {Object} New subtitle options + * + */ + setTitle: function (titleOptions, subtitleOptions) { + var chart = this, + options = chart.options, + chartTitleOptions, + chartSubtitleOptions; + + chart.chartTitleOptions = chartTitleOptions = merge(options.title, titleOptions); + chart.chartSubtitleOptions = chartSubtitleOptions = merge(options.subtitle, subtitleOptions); + + // add title and subtitle + each([ + ['title', titleOptions, chartTitleOptions], + ['subtitle', subtitleOptions, chartSubtitleOptions] + ], function (arr) { + var name = arr[0], + title = chart[name], + titleOptions = arr[1], + chartTitleOptions = arr[2]; + + if (title && titleOptions) { + title = title.destroy(); // remove old + } + if (chartTitleOptions && chartTitleOptions.text && !title) { + chart[name] = chart.renderer.text( + chartTitleOptions.text, + 0, + 0, + chartTitleOptions.useHTML + ) + .attr({ + align: chartTitleOptions.align, + 'class': PREFIX + name, + zIndex: chartTitleOptions.zIndex || 4 + }) + .css(chartTitleOptions.style) + .add() + .align(chartTitleOptions, false, chart.spacingBox); + } + }); + + }, + + /** + * Get chart width and height according to options and container size + */ + getChartSize: function () { + var chart = this, + optionsChart = chart.options.chart, + renderTo = chart.renderToClone || chart.renderTo; + + // get inner width and height from jQuery (#824) + chart.containerWidth = adapterRun(renderTo, 'width'); + chart.containerHeight = adapterRun(renderTo, 'height'); + + chart.chartWidth = optionsChart.width || chart.containerWidth || 600; + chart.chartHeight = optionsChart.height || + // the offsetHeight of an empty container is 0 in standard browsers, but 19 in IE7: + (chart.containerHeight > 19 ? chart.containerHeight : 400); + }, + + /** + * Create a clone of the chart's renderTo div and place it outside the viewport to allow + * size computation on chart.render and chart.redraw + */ + cloneRenderTo: function (revert) { + var clone = this.renderToClone, + container = this.container; + + // Destroy the clone and bring the container back to the real renderTo div + if (revert) { + if (clone) { + this.renderTo.appendChild(container); + discardElement(clone); + delete this.renderToClone; + } + + // Set up the clone + } else { + if (container) { + this.renderTo.removeChild(container); // do not clone this + } + this.renderToClone = clone = this.renderTo.cloneNode(0); + css(clone, { + position: ABSOLUTE, + top: '-9999px', + display: 'block' // #833 + }); + doc.body.appendChild(clone); + if (container) { + clone.appendChild(container); + } + } + }, + + /** + * Get the containing element, determine the size and create the inner container + * div to hold the chart + */ + getContainer: function () { + var chart = this, + container, + optionsChart = chart.options.chart, + chartWidth, + chartHeight, + renderTo, + containerId; + + chart.renderTo = renderTo = optionsChart.renderTo; + containerId = PREFIX + idCounter++; + + if (isString(renderTo)) { + chart.renderTo = renderTo = doc.getElementById(renderTo); + } + + // Display an error if the renderTo is wrong + if (!renderTo) { + error(13, true); + } + + // remove previous chart + renderTo.innerHTML = ''; + + // If the container doesn't have an offsetWidth, it has or is a child of a node + // that has display:none. We need to temporarily move it out to a visible + // state to determine the size, else the legend and tooltips won't render + // properly + if (!renderTo.offsetWidth) { + chart.cloneRenderTo(); + } + + // get the width and height + chart.getChartSize(); + chartWidth = chart.chartWidth; + chartHeight = chart.chartHeight; + + // create the inner container + chart.container = container = createElement(DIV, { + className: PREFIX + 'container' + + (optionsChart.className ? ' ' + optionsChart.className : ''), + id: containerId + }, extend({ + position: RELATIVE, + overflow: HIDDEN, // needed for context menu (avoid scrollbars) and + // content overflow in IE + width: chartWidth + PX, + height: chartHeight + PX, + textAlign: 'left', + lineHeight: 'normal' // #427 + }, optionsChart.style), + chart.renderToClone || renderTo + ); + + chart.renderer = + optionsChart.forExport ? // force SVG, used for SVG export + new SVGRenderer(container, chartWidth, chartHeight, true) : + new Renderer(container, chartWidth, chartHeight); + + if (useCanVG) { + // If we need canvg library, extend and configure the renderer + // to get the tracker for translating mouse events + chart.renderer.create(chart, container, chartWidth, chartHeight); + } + }, + + /** + * Calculate margins by rendering axis labels in a preliminary position. Title, + * subtitle and legend have already been rendered at this stage, but will be + * moved into their final positions + */ + getMargins: function () { + var chart = this, + optionsChart = chart.options.chart, + spacingTop = optionsChart.spacingTop, + spacingRight = optionsChart.spacingRight, + spacingBottom = optionsChart.spacingBottom, + spacingLeft = optionsChart.spacingLeft, + axisOffset, + legend = chart.legend, + optionsMarginTop = chart.optionsMarginTop, + optionsMarginLeft = chart.optionsMarginLeft, + optionsMarginRight = chart.optionsMarginRight, + optionsMarginBottom = chart.optionsMarginBottom, + chartTitleOptions = chart.chartTitleOptions, + chartSubtitleOptions = chart.chartSubtitleOptions, + legendOptions = chart.options.legend, + legendMargin = pick(legendOptions.margin, 10), + legendX = legendOptions.x, + legendY = legendOptions.y, + align = legendOptions.align, + verticalAlign = legendOptions.verticalAlign, + titleOffset; + + chart.resetMargins(); + axisOffset = chart.axisOffset; + + // adjust for title and subtitle + if ((chart.title || chart.subtitle) && !defined(chart.optionsMarginTop)) { + titleOffset = mathMax( + (chart.title && !chartTitleOptions.floating && !chartTitleOptions.verticalAlign && chartTitleOptions.y) || 0, + (chart.subtitle && !chartSubtitleOptions.floating && !chartSubtitleOptions.verticalAlign && chartSubtitleOptions.y) || 0 + ); + if (titleOffset) { + chart.plotTop = mathMax(chart.plotTop, titleOffset + pick(chartTitleOptions.margin, 15) + spacingTop); + } + } + // adjust for legend + if (legend.display && !legendOptions.floating) { + if (align === 'right') { // horizontal alignment handled first + if (!defined(optionsMarginRight)) { + chart.marginRight = mathMax( + chart.marginRight, + legend.legendWidth - legendX + legendMargin + spacingRight + ); + } + } else if (align === 'left') { + if (!defined(optionsMarginLeft)) { + chart.plotLeft = mathMax( + chart.plotLeft, + legend.legendWidth + legendX + legendMargin + spacingLeft + ); + } + + } else if (verticalAlign === 'top') { + if (!defined(optionsMarginTop)) { + chart.plotTop = mathMax( + chart.plotTop, + legend.legendHeight + legendY + legendMargin + spacingTop + ); + } + + } else if (verticalAlign === 'bottom') { + if (!defined(optionsMarginBottom)) { + chart.marginBottom = mathMax( + chart.marginBottom, + legend.legendHeight - legendY + legendMargin + spacingBottom + ); + } + } + } + + // adjust for scroller + if (chart.extraBottomMargin) { + chart.marginBottom += chart.extraBottomMargin; + } + if (chart.extraTopMargin) { + chart.plotTop += chart.extraTopMargin; + } + + // pre-render axes to get labels offset width + if (chart.hasCartesianSeries) { + each(chart.axes, function (axis) { + axis.getOffset(); + }); + } + + if (!defined(optionsMarginLeft)) { + chart.plotLeft += axisOffset[3]; + } + if (!defined(optionsMarginTop)) { + chart.plotTop += axisOffset[0]; + } + if (!defined(optionsMarginBottom)) { + chart.marginBottom += axisOffset[2]; + } + if (!defined(optionsMarginRight)) { + chart.marginRight += axisOffset[1]; + } + + chart.setChartSize(); + + }, + + /** + * Add the event handlers necessary for auto resizing + * + */ + initReflow: function () { + var chart = this, + optionsChart = chart.options.chart, + renderTo = chart.renderTo; + + var reflowTimeout; + + function reflow(e) { + var width = optionsChart.width || adapterRun(renderTo, 'width'), + height = optionsChart.height || adapterRun(renderTo, 'height'), + target = e ? e.target : win; // #805 - MooTools doesn't supply e + + // Width and height checks for display:none. Target is doc in IE8 and Opera, + // win in Firefox, Chrome and IE9. + if (width && height && (target === win || target === doc)) { + + if (width !== chart.containerWidth || height !== chart.containerHeight) { + clearTimeout(reflowTimeout); + reflowTimeout = setTimeout(function () { + chart.resize(width, height, false); + }, 100); + } + chart.containerWidth = width; + chart.containerHeight = height; + } + } + + addEvent(win, 'resize', reflow); + addEvent(chart, 'destroy', function () { + removeEvent(win, 'resize', reflow); + }); + }, + + /** + * Fires endResize event on chart instance. + */ + fireEndResize: function () { + var chart = this; + + if (chart) { + fireEvent(chart, 'endResize', null, function () { + chart.isResizing -= 1; + }); + } + }, + + /** + * Resize the chart to a given width and height + * @param {Number} width + * @param {Number} height + * @param {Object|Boolean} animation + */ + // TODO: This method is called setSize in the api + resize: function (width, height, animation) { + var chart = this, + chartWidth, + chartHeight, + spacingBox, + chartTitle = chart.title, + chartSubtitle = chart.subtitle; + + chart.isResizing += 1; + + // set the animation for the current process + setAnimation(animation, chart); + + chart.oldChartHeight = chart.chartHeight; + chart.oldChartWidth = chart.chartWidth; + if (defined(width)) { + chart.chartWidth = chartWidth = mathRound(width); + } + if (defined(height)) { + chart.chartHeight = chartHeight = mathRound(height); + } + + css(chart.container, { + width: chartWidth + PX, + height: chartHeight + PX + }); + chart.renderer.setSize(chartWidth, chartHeight, animation); + + // update axis lengths for more correct tick intervals: + chart.plotWidth = chartWidth - chart.plotLeft - chart.marginRight; + chart.plotHeight = chartHeight - chart.plotTop - chart.marginBottom; + + // handle axes + chart.maxTicks = null; + each(chart.axes, function (axis) { + axis.isDirty = true; + axis.setScale(); + }); + + // make sure non-cartesian series are also handled + each(chart.series, function (serie) { + serie.isDirty = true; + }); + + chart.isDirtyLegend = true; // force legend redraw + chart.isDirtyBox = true; // force redraw of plot and chart border + + chart.getMargins(); + + // move titles + spacingBox = chart.spacingBox; + if (chartTitle) { + chartTitle.align(null, null, spacingBox); + } + if (chartSubtitle) { + chartSubtitle.align(null, null, spacingBox); + } + + chart.redraw(animation); + + + chart.oldChartHeight = null; + fireEvent(chart, 'resize'); + + // fire endResize and set isResizing back + // If animation is disabled, fire without delay + if (globalAnimation === false) { + chart.fireEndResize(); + } else { // else set a timeout with the animation duration + setTimeout(chart.fireEndResize, (globalAnimation && globalAnimation.duration) || 500); + } + }, + + /** + * Set the public chart properties. This is done before and after the pre-render + * to determine margin sizes + */ + setChartSize: function () { + var chart = this, + inverted = chart.inverted, + chartWidth = chart.chartWidth, + chartHeight = chart.chartHeight, + optionsChart = chart.options.chart, + spacingTop = optionsChart.spacingTop, + spacingRight = optionsChart.spacingRight, + spacingBottom = optionsChart.spacingBottom, + spacingLeft = optionsChart.spacingLeft; + + chart.plotLeft = mathRound(chart.plotLeft); + chart.plotTop = mathRound(chart.plotTop); + chart.plotWidth = mathRound(chartWidth - chart.plotLeft - chart.marginRight); + chart.plotHeight = mathRound(chartHeight - chart.plotTop - chart.marginBottom); + + chart.plotSizeX = inverted ? chart.plotHeight : chart.plotWidth; + chart.plotSizeY = inverted ? chart.plotWidth : chart.plotHeight; + + chart.spacingBox = { + x: spacingLeft, + y: spacingTop, + width: chartWidth - spacingLeft - spacingRight, + height: chartHeight - spacingTop - spacingBottom + }; + + each(chart.axes, function (axis) { + axis.setAxisSize(); + axis.setAxisTranslation(); + }); + }, + + /** + * Initial margins before auto size margins are applied + */ + resetMargins: function () { + var chart = this, + optionsChart = chart.options.chart, + spacingTop = optionsChart.spacingTop, + spacingRight = optionsChart.spacingRight, + spacingBottom = optionsChart.spacingBottom, + spacingLeft = optionsChart.spacingLeft; + + chart.plotTop = pick(chart.optionsMarginTop, spacingTop); + chart.marginRight = pick(chart.optionsMarginRight, spacingRight); + chart.marginBottom = pick(chart.optionsMarginBottom, spacingBottom); + chart.plotLeft = pick(chart.optionsMarginLeft, spacingLeft); + chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left + }, + + /** + * Draw the borders and backgrounds for chart and plot area + */ + drawChartBox: function () { + var chart = this, + optionsChart = chart.options.chart, + renderer = chart.renderer, + chartWidth = chart.chartWidth, + chartHeight = chart.chartHeight, + chartBackground = chart.chartBackground, + plotBackground = chart.plotBackground, + plotBorder = chart.plotBorder, + plotBGImage = chart.plotBGImage, + chartBorderWidth = optionsChart.borderWidth || 0, + chartBackgroundColor = optionsChart.backgroundColor, + plotBackgroundColor = optionsChart.plotBackgroundColor, + plotBackgroundImage = optionsChart.plotBackgroundImage, + mgn, + bgAttr, + plotSize = { + x: chart.plotLeft, + y: chart.plotTop, + width: chart.plotWidth, + height: chart.plotHeight + }; + + // Chart area + mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0); + + if (chartBorderWidth || chartBackgroundColor) { + if (!chartBackground) { + + bgAttr = { + fill: chartBackgroundColor || NONE + }; + if (chartBorderWidth) { // #980 + bgAttr.stroke = optionsChart.borderColor; + bgAttr['stroke-width'] = chartBorderWidth; + } + chart.chartBackground = renderer.rect(mgn / 2, mgn / 2, chartWidth - mgn, chartHeight - mgn, + optionsChart.borderRadius, chartBorderWidth) + .attr(bgAttr) + .add() + .shadow(optionsChart.shadow); + } else { // resize + chartBackground.animate( + chartBackground.crisp(null, null, null, chartWidth - mgn, chartHeight - mgn) + ); + } + } + + + // Plot background + if (plotBackgroundColor) { + if (!plotBackground) { + chart.plotBackground = renderer.rect(chart.plotLeft, chart.plotTop, chart.plotWidth, chart.plotHeight, 0) + .attr({ + fill: plotBackgroundColor + }) + .add() + .shadow(optionsChart.plotShadow); + } else { + plotBackground.animate(plotSize); + } + } + if (plotBackgroundImage) { + if (!plotBGImage) { + chart.plotBGImage = renderer.image(plotBackgroundImage, chart.plotLeft, chart.plotTop, chart.plotWidth, chart.plotHeight) + .add(); + } else { + plotBGImage.animate(plotSize); + } + } + + // Plot area border + if (optionsChart.plotBorderWidth) { + if (!plotBorder) { + chart.plotBorder = renderer.rect(chart.plotLeft, chart.plotTop, chart.plotWidth, chart.plotHeight, 0, optionsChart.plotBorderWidth) + .attr({ + stroke: optionsChart.plotBorderColor, + 'stroke-width': optionsChart.plotBorderWidth, + zIndex: 4 + }) + .add(); + } else { + plotBorder.animate( + plotBorder.crisp(null, chart.plotLeft, chart.plotTop, chart.plotWidth, chart.plotHeight) + ); + } + } + + // reset + chart.isDirtyBox = false; + }, + + /** + * Detect whether a certain chart property is needed based on inspecting its options + * and series. This mainly applies to the chart.invert property, and in extensions to + * the chart.angular and chart.polar properties. + */ + propFromSeries: function () { + var chart = this, + optionsChart = chart.options.chart, + klass, + seriesOptions = chart.options.series, + i, + value; + + + each(['inverted', 'angular', 'polar'], function (key) { + + // The default series type's class + klass = seriesTypes[optionsChart.type || optionsChart.defaultSeriesType]; + + // Get the value from available chart-wide properties + value = ( + chart[key] || // 1. it is set before + optionsChart[key] || // 2. it is set in the options + (klass && klass.prototype[key]) // 3. it's default series class requires it + ); + + // 4. Check if any the chart's series require it + i = seriesOptions && seriesOptions.length; + while (!value && i--) { + klass = seriesTypes[seriesOptions[i].type]; + if (klass && klass.prototype[key]) { + value = true; + } + } + + // Set the chart property + chart[key] = value; + }); + + }, + + /** + * Render all graphics for the chart + */ + render: function () { + var chart = this, + axes = chart.axes, + renderer = chart.renderer, + options = chart.options; + + var labels = options.labels, + credits = options.credits, + creditsHref; + + // Title + chart.setTitle(); + + + // Legend + chart.legend = new Legend(chart); + + // Get margins by pre-rendering axes + // set axes scales + each(axes, function (axis) { + axis.setScale(); + }); + chart.getMargins(); + + chart.maxTicks = null; // reset for second pass + each(axes, function (axis) { + axis.setTickPositions(true); // update to reflect the new margins + axis.setMaxTicks(); + }); + chart.adjustTickAmounts(); + chart.getMargins(); // second pass to check for new labels + + + // Draw the borders and backgrounds + chart.drawChartBox(); + + + // Axes + if (chart.hasCartesianSeries) { + each(axes, function (axis) { + axis.render(); + }); + } + + // The series + if (!chart.seriesGroup) { + chart.seriesGroup = renderer.g('series-group') + .attr({ zIndex: 3 }) + .add(); + } + each(chart.series, function (serie) { + serie.translate(); + serie.setTooltipPoints(); + serie.render(); + }); + + // Labels + if (labels.items) { + each(labels.items, function () { + var style = extend(labels.style, this.style), + x = pInt(style.left) + chart.plotLeft, + y = pInt(style.top) + chart.plotTop + 12; + + // delete to prevent rewriting in IE + delete style.left; + delete style.top; + + renderer.text( + this.html, + x, + y + ) + .attr({ zIndex: 2 }) + .css(style) + .add(); + + }); + } + + // Credits + if (credits.enabled && !chart.credits) { + creditsHref = credits.href; + chart.credits = renderer.text( + credits.text, + 0, + 0 + ) + .on('click', function () { + if (creditsHref) { + location.href = creditsHref; + } + }) + .attr({ + align: credits.position.align, + zIndex: 8 + }) + .css(credits.style) + .add() + .align(credits.position); + } + + // Set flag + chart.hasRendered = true; + + }, + + /** + * Clean up memory usage + */ + destroy: function () { + var chart = this, + axes = chart.axes, + series = chart.series, + container = chart.container; + + var i, + parentNode = container && container.parentNode; + + // If the chart is destroyed already, do nothing. + // This will happen if if a script invokes chart.destroy and + // then it will be called again on win.unload + if (chart === null) { + return; + } + + // fire the chart.destoy event + fireEvent(chart, 'destroy'); + + // remove events + removeEvent(chart); + + // ==== Destroy collections: + // Destroy axes + i = axes.length; + while (i--) { + axes[i] = axes[i].destroy(); + } + + // Destroy each series + i = series.length; + while (i--) { + series[i] = series[i].destroy(); + } + + // ==== Destroy chart properties: + each(['title', 'subtitle', 'chartBackground', 'plotBackground', 'plotBGImage', 'plotBorder', 'seriesGroup', 'clipRect', 'credits', 'tracker', 'scroller', 'rangeSelector', 'legend', 'resetZoomButton', 'tooltip', 'renderer'], function (name) { + var prop = chart[name]; + + if (prop) { + chart[name] = prop.destroy(); + } + }); + + // remove container and all SVG + if (container) { // can break in IE when destroyed before finished loading + container.innerHTML = ''; + removeEvent(container); + if (parentNode) { + discardElement(container); + } + + // IE6 leak + container = null; + } + + // clean it all up + for (i in chart) { + delete chart[i]; + } + + chart.options = null; + chart = null; + }, + + /** + * Prepare for first rendering after all data are loaded + */ + firstRender: function () { + var chart = this, + options = chart.options, + callback = chart.callback; + + // VML namespaces can't be added until after complete. Listening + // for Perini's doScroll hack is not enough. + var ONREADYSTATECHANGE = 'onreadystatechange', + COMPLETE = 'complete'; + // Note: in spite of JSLint's complaints, win == win.top is required + /*jslint eqeq: true*/ + if ((!hasSVG && (win == win.top && doc.readyState !== COMPLETE)) || (useCanVG && !win.canvg)) { + /*jslint eqeq: false*/ + if (useCanVG) { + // Delay rendering until canvg library is downloaded and ready + CanVGController.push(function () { + chart.firstRender(); + }, options.global.canvasToolsURL); + } else { + doc.attachEvent(ONREADYSTATECHANGE, function () { + doc.detachEvent(ONREADYSTATECHANGE, chart.firstRender); + if (doc.readyState === COMPLETE) { + chart.firstRender(); + } + }); + } + return; + } + + // create the container + chart.getContainer(); + + // Run an early event after the container and renderer are established + fireEvent(chart, 'init'); + + // Initialize range selector for stock charts + if (Highcharts.RangeSelector && options.rangeSelector.enabled) { + chart.rangeSelector = new Highcharts.RangeSelector(chart); + } + + chart.resetMargins(); + chart.setChartSize(); + + // Set the common chart properties (mainly invert) from the given series + chart.propFromSeries(); + + // get axes + chart.getAxes(); + + // Initialize the series + each(options.series || [], function (serieOptions) { + chart.initSeries(serieOptions); + }); + + // Run an event where series and axes can be added + //fireEvent(chart, 'beforeRender'); + + // Initialize scroller for stock charts + if (Highcharts.Scroller && (options.navigator.enabled || options.scrollbar.enabled)) { + chart.scroller = new Highcharts.Scroller(chart); + } + + // depends on inverted and on margins being set + chart.tracker = new MouseTracker(chart, options); + + chart.render(); + + // add canvas + chart.renderer.draw(); + // run callbacks + if (callback) { + callback.apply(chart, [chart]); + } + each(chart.callbacks, function (fn) { + fn.apply(chart, [chart]); + }); + + + // If the chart was rendered outside the top container, put it back in + chart.cloneRenderTo(true); + + fireEvent(chart, 'load'); + + }, + + init: function (chartEvents) { + var chart = this, + optionsChart = chart.options.chart, + eventType; + + // Run chart + + // Set up auto resize + if (optionsChart.reflow !== false) { + addEvent(chart, 'load', chart.initReflow); + } + + // Chart event handlers + if (chartEvents) { + for (eventType in chartEvents) { + addEvent(chart, eventType, chartEvents[eventType]); + } + } + + chart.xAxis = []; + chart.yAxis = []; + + // Expose methods and variables + chart.animation = useCanVG ? false : pick(optionsChart.animation, true); + chart.setSize = chart.resize; + chart.pointCount = 0; + chart.counters = new ChartCounters(); + /* + if ($) $(function () { + $container = $('#container'); + var origChartWidth, + origChartHeight; + if ($container) { + $('') + .insertBefore($container) + .click(function () { + if (origChartWidth === UNDEFINED) { + origChartWidth = chartWidth; + origChartHeight = chartHeight; + } + chart.resize(chartWidth *= 1.1, chartHeight *= 1.1); + }); + $('') + .insertBefore($container) + .click(function () { + if (origChartWidth === UNDEFINED) { + origChartWidth = chartWidth; + origChartHeight = chartHeight; + } + chart.resize(chartWidth *= 0.9, chartHeight *= 0.9); + }); + $('') + .insertBefore($container) + .click(function () { + if (origChartWidth === UNDEFINED) { + origChartWidth = chartWidth; + origChartHeight = chartHeight; + } + chart.resize(origChartWidth, origChartHeight); + }); + } + }) + */ + + chart.firstRender(); + } + }; // end Chart + +// Hook for exporting module + Chart.prototype.callbacks = []; + /** + * The Point object and prototype. Inheritable and used as base for PiePoint + */ + var Point = function () { + }; + Point.prototype = { + + /** + * Initialize the point + * @param {Object} series The series object containing this point + * @param {Object} options The data in either number, array or object format + */ + init: function (series, options, x) { + var point = this, + counters = series.chart.counters, + defaultColors; + point.series = series; + point.applyOptions(options, x); + point.pointAttr = {}; + + if (series.options.colorByPoint) { + defaultColors = series.chart.options.colors; + if (!point.options) { + point.options = {}; + } + point.color = point.options.color = point.color || defaultColors[counters.color++]; + + // loop back to zero + counters.wrapColor(defaultColors.length); + } + + series.chart.pointCount++; + return point; + }, + /** + * Apply the options containing the x and y data and possible some extra properties. + * This is called on point init or from point.update. + * + * @param {Object} options + */ + applyOptions: function (options, x) { + var point = this, + series = point.series, + optionsType = typeof options; + + point.config = options; + + // onedimensional array input + if (optionsType === 'number' || options === null) { + point.y = options; + } else if (typeof options[0] === 'number') { // two-dimentional array + point.x = options[0]; + point.y = options[1]; + } else if (optionsType === 'object' && typeof options.length !== 'number') { // object input + // copy options directly to point + extend(point, options); + point.options = options; + + // This is the fastest way to detect if there are individual point dataLabels that need + // to be considered in drawDataLabels. These can only occur in object configs. + if (options.dataLabels) { + series._hasPointLabels = true; + } + } else if (typeof options[0] === 'string') { // categorized data with name in first position + point.name = options[0]; + point.y = options[1]; + } + + /* + * If no x is set by now, get auto incremented value. All points must have an + * x value, however the y value can be null to create a gap in the series + */ + // todo: skip this? It is only used in applyOptions, in translate it should not be used + if (point.x === UNDEFINED) { + point.x = x === UNDEFINED ? series.autoIncrement() : x; + } + + + }, + + /** + * Destroy a point to clear memory. Its reference still stays in series.data. + */ + destroy: function () { + var point = this, + series = point.series, + chart = series.chart, + hoverPoints = chart.hoverPoints, + prop; + + chart.pointCount--; + + if (hoverPoints) { + point.setState(); + erase(hoverPoints, point); + if (!hoverPoints.length) { + chart.hoverPoints = null; + } + + } + if (point === chart.hoverPoint) { + point.onMouseOut(); + } + + // remove all events + if (point.graphic || point.dataLabel) { // removeEvent and destroyElements are performance expensive + removeEvent(point); + point.destroyElements(); + } + + if (point.legendItem) { // pies have legend items + chart.legend.destroyItem(point); + } + + for (prop in point) { + point[prop] = null; + } + + + }, + + /** + * Destroy SVG elements associated with the point + */ + destroyElements: function () { + var point = this, + props = ['graphic', 'tracker', 'dataLabel', 'group', 'connector', 'shadowGroup'], + prop, + i = 6; + while (i--) { + prop = props[i]; + if (point[prop]) { + point[prop] = point[prop].destroy(); + } + } + }, + + /** + * Return the configuration hash needed for the data label and tooltip formatters + */ + getLabelConfig: function () { + var point = this; + return { + x: point.category, + y: point.y, + key: point.name || point.category, + series: point.series, + point: point, + percentage: point.percentage, + total: point.total || point.stackTotal + }; + }, + + /** + * Toggle the selection status of a point + * @param {Boolean} selected Whether to select or unselect the point. + * @param {Boolean} accumulate Whether to add to the previous selection. By default, + * this happens if the control key (Cmd on Mac) was pressed during clicking. + */ + select: function (selected, accumulate) { + var point = this, + series = point.series, + chart = series.chart; + + selected = pick(selected, !point.selected); + + // fire the event with the defalut handler + point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () { + point.selected = selected; + point.setState(selected && SELECT_STATE); + + // unselect all other points unless Ctrl or Cmd + click + if (!accumulate) { + each(chart.getSelectedPoints(), function (loopPoint) { + if (loopPoint.selected && loopPoint !== point) { + loopPoint.selected = false; + loopPoint.setState(NORMAL_STATE); + loopPoint.firePointEvent('unselect'); + } + }); + } + }); + }, + + onMouseOver: function () { + var point = this, + series = point.series, + chart = series.chart, + tooltip = chart.tooltip, + hoverPoint = chart.hoverPoint; + + // set normal state to previous series + if (hoverPoint && hoverPoint !== point) { + hoverPoint.onMouseOut(); + } + + // trigger the event + point.firePointEvent('mouseOver'); + + // update the tooltip + if (tooltip && (!tooltip.shared || series.noSharedTooltip)) { + tooltip.refresh(point); + } + + // hover this + point.setState(HOVER_STATE); + chart.hoverPoint = point; + }, + + onMouseOut: function () { + var point = this; + point.firePointEvent('mouseOut'); + + point.setState(); + point.series.chart.hoverPoint = null; + }, + + /** + * Extendable method for formatting each point's tooltip line + * + * @return {String} A string to be concatenated in to the common tooltip text + */ + tooltipFormatter: function (pointFormat) { + var point = this, + series = point.series, + seriesTooltipOptions = series.tooltipOptions, + match = pointFormat.match(/\{(series|point)\.[a-zA-Z]+\}/g), + splitter = /[{\.}]/, + obj, + key, + replacement, + repOptionKey, + parts, + prop, + i, + cfg = { // docs: percentageDecimals, percentagePrefix, percentageSuffix, totalDecimals, totalPrefix, totalSuffix + y: 0, // 0: use 'value' for repOptionKey + open: 0, + high: 0, + low: 0, + close: 0, + percentage: 1, // 1: use the self name for repOptionKey + total: 1 + }; + + // Backwards compatibility to y naming in early Highstock + seriesTooltipOptions.valuePrefix = seriesTooltipOptions.valuePrefix || seriesTooltipOptions.yPrefix; + seriesTooltipOptions.valueDecimals = seriesTooltipOptions.valueDecimals || seriesTooltipOptions.yDecimals; + seriesTooltipOptions.valueSuffix = seriesTooltipOptions.valueSuffix || seriesTooltipOptions.ySuffix; + + // loop over the variables defined on the form {series.name}, {point.y} etc + for (i in match) { + key = match[i]; + if (isString(key) && key !== pointFormat) { // IE matches more than just the variables + + // Split it further into parts + parts = (' ' + key).split(splitter); // add empty string because IE and the rest handles it differently + obj = { 'point': point, 'series': series }[parts[1]]; + prop = parts[2]; + + // Add some preformatting + if (obj === point && cfg.hasOwnProperty(prop)) { + repOptionKey = cfg[prop] ? prop : 'value'; + replacement = (seriesTooltipOptions[repOptionKey + 'Prefix'] || '') + + numberFormat(point[prop], pick(seriesTooltipOptions[repOptionKey + 'Decimals'], -1)) + + (seriesTooltipOptions[repOptionKey + 'Suffix'] || ''); + + // Automatic replacement + } else { + replacement = obj[prop]; + } + + pointFormat = pointFormat.replace(key, replacement); + } + } + + return pointFormat; + }, + + /** + * Update the point with new options (typically x/y data) and optionally redraw the series. + * + * @param {Object} options Point options as defined in the series.data array + * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + * + */ + update: function (options, redraw, animation) { + var point = this, + series = point.series, + graphic = point.graphic, + i, + data = series.data, + dataLength = data.length, + chart = series.chart; + + redraw = pick(redraw, true); + + // fire the event with a default handler of doing the update + point.firePointEvent('update', { options: options }, function () { + + point.applyOptions(options); + + // update visuals + if (isObject(options)) { + series.getAttribs(); + if (graphic) { + graphic.attr(point.pointAttr[series.state]); + } + } + + // record changes in the parallel arrays + for (i = 0; i < dataLength; i++) { + if (data[i] === point) { + series.xData[i] = point.x; + series.yData[i] = point.y; + series.options.data[i] = options; + break; + } + } + + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(animation); + } + }); + }, + + /** + * Remove a point and optionally redraw the series and if necessary the axes + * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + */ + remove: function (redraw, animation) { + var point = this, + series = point.series, + chart = series.chart, + i, + data = series.data, + dataLength = data.length; + + setAnimation(animation, chart); + redraw = pick(redraw, true); + + // fire the event with a default handler of removing the point + point.firePointEvent('remove', null, function () { + + //erase(series.data, point); + + for (i = 0; i < dataLength; i++) { + if (data[i] === point) { + + // splice all the parallel arrays + data.splice(i, 1); + series.options.data.splice(i, 1); + series.xData.splice(i, 1); + series.yData.splice(i, 1); + break; + } + } + + point.destroy(); + + + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(); + } + }); + + + }, + + /** + * Fire an event on the Point object. Must not be renamed to fireEvent, as this + * causes a name clash in MooTools + * @param {String} eventType + * @param {Object} eventArgs Additional event arguments + * @param {Function} defaultFunction Default event handler + */ + firePointEvent: function (eventType, eventArgs, defaultFunction) { + var point = this, + series = this.series, + seriesOptions = series.options; + + // load event handlers on demand to save time on mouseover/out + if (seriesOptions.point.events[eventType] || (point.options && point.options.events && point.options.events[eventType])) { + this.importEvents(); + } + + // add default handler if in selection mode + if (eventType === 'click' && seriesOptions.allowPointSelect) { + defaultFunction = function (event) { + // Control key is for Windows, meta (= Cmd key) for Mac, Shift for Opera + point.select(null, event.ctrlKey || event.metaKey || event.shiftKey); + }; + } + + fireEvent(this, eventType, eventArgs, defaultFunction); + }, + /** + * Import events from the series' and point's options. Only do it on + * demand, to save processing time on hovering. + */ + importEvents: function () { + if (!this.hasImportedEvents) { + var point = this, + options = merge(point.series.options.point, point.options), + events = options.events, + eventType; + + point.events = events; + + for (eventType in events) { + addEvent(point, eventType, events[eventType]); + } + this.hasImportedEvents = true; + + } + }, + + /** + * Set the point's state + * @param {String} state + */ + setState: function (state) { + var point = this, + plotX = point.plotX, + plotY = point.plotY, + series = point.series, + stateOptions = series.options.states, + markerOptions = defaultPlotOptions[series.type].marker && series.options.marker, + normalDisabled = markerOptions && !markerOptions.enabled, + markerStateOptions = markerOptions && markerOptions.states[state], + stateDisabled = markerStateOptions && markerStateOptions.enabled === false, + stateMarkerGraphic = series.stateMarkerGraphic, + chart = series.chart, + radius, + pointAttr = point.pointAttr; + + state = state || NORMAL_STATE; // empty string + + if ( + // already has this state + state === point.state || + // selected points don't respond to hover + (point.selected && state !== SELECT_STATE) || + // series' state options is disabled + (stateOptions[state] && stateOptions[state].enabled === false) || + // point marker's state options is disabled + (state && (stateDisabled || (normalDisabled && !markerStateOptions.enabled))) + + ) { + return; + } + + // apply hover styles to the existing point + if (point.graphic) { + radius = markerOptions && point.graphic.symbolName && pointAttr[state].r; + point.graphic.attr(merge( + pointAttr[state], + radius ? { // new symbol attributes (#507, #612) + x: plotX - radius, + y: plotY - radius, + width: 2 * radius, + height: 2 * radius + } : {} + )); + } else { + // if a graphic is not applied to each point in the normal state, create a shared + // graphic for the hover state + if (state && markerStateOptions) { + if (!stateMarkerGraphic) { + radius = markerStateOptions.radius; + series.stateMarkerGraphic = stateMarkerGraphic = chart.renderer.symbol( + series.symbol, + -radius, + -radius, + 2 * radius, + 2 * radius + ) + .attr(pointAttr[state]) + .add(series.group); + } + + stateMarkerGraphic.translate( + plotX, + plotY + ); + } + + if (stateMarkerGraphic) { + stateMarkerGraphic[state ? 'show' : 'hide'](); + } + } + + point.state = state; + } + }; + + /** + * @classDescription The base function which all other series types inherit from. The data in the series is stored + * in various arrays. + * + * - First, series.options.data contains all the original config options for + * each point whether added by options or methods like series.addPoint. + * - Next, series.data contains those values converted to points, but in case the series data length + * exceeds the cropThreshold, or if the data is grouped, series.data doesn't contain all the points. It + * only contains the points that have been created on demand. + * - Then there's series.points that contains all currently visible point objects. In case of cropping, + * the cropped-away points are not part of this array. The series.points array starts at series.cropStart + * compared to series.data and series.options.data. If however the series data is grouped, these can't + * be correlated one to one. + * - series.xData and series.processedXData contain clean x values, equivalent to series.data and series.points. + * - series.yData and series.processedYData contain clean x values, equivalent to series.data and series.points. + * + * @param {Object} chart + * @param {Object} options + */ + var Series = function () { + }; + + Series.prototype = { + + isCartesian: true, + type: 'line', + pointClass: Point, + sorted: true, // requires the data to be sorted + pointAttrToOptions: { // mapping between SVG attributes and the corresponding options + stroke: 'lineColor', + 'stroke-width': 'lineWidth', + fill: 'fillColor', + r: 'radius' + }, + init: function (chart, options) { + var series = this, + eventType, + events, + //pointEvent, + index = chart.series.length; + + series.chart = chart; + series.options = options = series.setOptions(options); // merge with plotOptions + + // bind the axes + series.bindAxes(); + + // set some variables + extend(series, { + index: index, + name: options.name || 'Series ' + (index + 1), + state: NORMAL_STATE, + pointAttr: {}, + visible: options.visible !== false, // true by default + selected: options.selected === true // false by default + }); + + // special + if (useCanVG) { + options.animation = false; + } + + // register event listeners + events = options.events; + for (eventType in events) { + addEvent(series, eventType, events[eventType]); + } + if ( + (events && events.click) || + (options.point && options.point.events && options.point.events.click) || + options.allowPointSelect + ) { + chart.runTrackerClick = true; + } + + series.getColor(); + series.getSymbol(); + + // set the data + series.setData(options.data, false); + + // Mark cartesian + if (series.isCartesian) { + chart.hasCartesianSeries = true; + } + + // Register it in the chart + chart.series.push(series); + }, + + /** + * Set the xAxis and yAxis properties of cartesian series, and register the series + * in the axis.series array + */ + bindAxes: function () { + var series = this, + seriesOptions = series.options, + chart = series.chart, + axisOptions; + + if (series.isCartesian) { + + each(['xAxis', 'yAxis'], function (AXIS) { // repeat for xAxis and yAxis + + each(chart[AXIS], function (axis) { // loop through the chart's axis objects + + axisOptions = axis.options; + + // apply if the series xAxis or yAxis option mathches the number of the + // axis, or if undefined, use the first axis + if ((seriesOptions[AXIS] === axisOptions.index) || + (seriesOptions[AXIS] === UNDEFINED && axisOptions.index === 0)) { + + // register this series in the axis.series lookup + axis.series.push(series); + + // set this series.xAxis or series.yAxis reference + series[AXIS] = axis; + + // mark dirty for redraw + axis.isDirty = true; + } + }); + + }); + } + }, + + + /** + * Return an auto incremented x value based on the pointStart and pointInterval options. + * This is only used if an x value is not given for the point that calls autoIncrement. + */ + autoIncrement: function () { + var series = this, + options = series.options, + xIncrement = series.xIncrement; + + xIncrement = pick(xIncrement, options.pointStart, 0); + + series.pointInterval = pick(series.pointInterval, options.pointInterval, 1); + + series.xIncrement = xIncrement + series.pointInterval; + return xIncrement; + }, + + /** + * Divide the series data into segments divided by null values. + */ + getSegments: function () { + var series = this, + lastNull = -1, + segments = [], + i, + points = series.points, + pointsLength = points.length; + + if (pointsLength) { // no action required for [] + + // if connect nulls, just remove null points + if (series.options.connectNulls) { + i = pointsLength; + while (i--) { + if (points[i].y === null) { + points.splice(i, 1); + } + } + if (points.length) { + segments = [points]; + } + + // else, split on null points + } else { + each(points, function (point, i) { + if (point.y === null) { + if (i > lastNull + 1) { + segments.push(points.slice(lastNull + 1, i)); + } + lastNull = i; + } else if (i === pointsLength - 1) { // last value + segments.push(points.slice(lastNull + 1, i + 1)); + } + }); + } + } + + // register it + series.segments = segments; + }, + /** + * Set the series options by merging from the options tree + * @param {Object} itemOptions + */ + setOptions: function (itemOptions) { + var series = this, + chart = series.chart, + chartOptions = chart.options, + plotOptions = chartOptions.plotOptions, + data = itemOptions.data, + options; + + itemOptions.data = null; // remove from merge to prevent looping over the data set + + options = merge( + plotOptions[this.type], + plotOptions.series, + itemOptions + ); + + // Re-insert the data array to the options and the original config (#717) + options.data = itemOptions.data = data; + + // the tooltip options are merged between global and series specific options + series.tooltipOptions = merge(chartOptions.tooltip, options.tooltip); + + return options; + + }, + /** + * Get the series' color + */ + getColor: function () { + var options = this.options, + defaultColors = this.chart.options.colors, + counters = this.chart.counters; + this.color = options.color || + (!options.colorByPoint && defaultColors[counters.color++]) || 'gray'; + counters.wrapColor(defaultColors.length); + }, + /** + * Get the series' symbol + */ + getSymbol: function () { + var series = this, + seriesMarkerOption = series.options.marker, + chart = series.chart, + defaultSymbols = chart.options.symbols, + counters = chart.counters; + series.symbol = seriesMarkerOption.symbol || defaultSymbols[counters.symbol++]; + + // don't substract radius in image symbols (#604) + if (/^url/.test(series.symbol)) { + seriesMarkerOption.radius = 0; + } + counters.wrapSymbol(defaultSymbols.length); + }, + + /** + * Get the series' symbol in the legend. This method should be overridable to create custom + * symbols through Highcharts.seriesTypes[type].prototype.drawLegendSymbols. + * + * @param {Object} legend The legend object + */ + drawLegendSymbol: function (legend) { + + var options = this.options, + markerOptions = options.marker, + radius, + legendOptions = legend.options, + legendSymbol, + symbolWidth = legendOptions.symbolWidth, + renderer = this.chart.renderer, + legendItemGroup = this.legendGroup, + baseline = legend.baseline, + attr; + + // Draw the line + if (options.lineWidth) { + attr = { + 'stroke-width': options.lineWidth + }; + if (options.dashStyle) { + attr.dashstyle = options.dashStyle; + } + this.legendLine = renderer.path([ + M, + 0, + baseline - 4, + L, + symbolWidth, + baseline - 4 + ]) + .attr(attr) + .add(legendItemGroup); + } + + // Draw the marker + if (markerOptions && markerOptions.enabled) { + radius = markerOptions.radius; + this.legendSymbol = legendSymbol = renderer.symbol( + this.symbol, + (symbolWidth / 2) - radius, + baseline - 4 - radius, + 2 * radius, + 2 * radius + ) + .attr(this.pointAttr[NORMAL_STATE]) + .add(legendItemGroup); + } + }, + + /** + * Add a point dynamically after chart load time + * @param {Object} options Point options as given in series.data + * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call + * @param {Boolean} shift If shift is true, a point is shifted off the start + * of the series as one is appended to the end. + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + */ + addPoint: function (options, redraw, shift, animation) { + var series = this, + data = series.data, + graph = series.graph, + area = series.area, + chart = series.chart, + xData = series.xData, + yData = series.yData, + currentShift = (graph && graph.shift) || 0, + dataOptions = series.options.data, + point; + //point = (new series.pointClass()).init(series, options); + + setAnimation(animation, chart); + + // Make graph animate sideways + if (graph && shift) { + graph.shift = currentShift + 1; + } + if (area) { + if (shift) { // #780 + area.shift = currentShift + 1; + } + area.isArea = true; // needed in animation, both with and without shift + } + + // Optional redraw, defaults to true + redraw = pick(redraw, true); + + // Get options and push the point to xData, yData and series.options. In series.generatePoints + // the Point instance will be created on demand and pushed to the series.data array. + point = { series: series }; + series.pointClass.prototype.applyOptions.apply(point, [options]); + xData.push(point.x); + yData.push(series.valueCount === 4 ? [point.open, point.high, point.low, point.close] : point.y); + dataOptions.push(options); + + + // Shift the first point off the parallel arrays + // todo: consider series.removePoint(i) method + if (shift) { + if (data[0] && data[0].remove) { + data[0].remove(false); + } else { + data.shift(); + xData.shift(); + yData.shift(); + dataOptions.shift(); + } + } + series.getAttribs(); + + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(); + } + }, + + /** + * Replace the series data with a new set of data + * @param {Object} data + * @param {Object} redraw + */ + setData: function (data, redraw) { + var series = this, + oldData = series.points, + options = series.options, + initialColor = series.initialColor, + chart = series.chart, + firstPoint = null, + xAxis = series.xAxis, + i, + pointProto = series.pointClass.prototype; + + // reset properties + series.xIncrement = null; + series.pointRange = (xAxis && xAxis.categories && 1) || options.pointRange; + + if (defined(initialColor)) { // reset colors for pie + chart.counters.color = initialColor; + } + + // parallel arrays + var xData = [], + yData = [], + dataLength = data ? data.length : [], + turboThreshold = options.turboThreshold || 1000, + pt, + valueCount = series.valueCount; + + // In turbo mode, only one- or twodimensional arrays of numbers are allowed. The + // first value is tested, and we assume that all the rest are defined the same + // way. Although the 'for' loops are similar, they are repeated inside each + // if-else conditional for max performance. + if (dataLength > turboThreshold) { + + // find the first non-null point + i = 0; + while (firstPoint === null && i < dataLength) { + firstPoint = data[i]; + i++; + } + + + if (isNumber(firstPoint)) { // assume all points are numbers + var x = pick(options.pointStart, 0), + pointInterval = pick(options.pointInterval, 1); + + for (i = 0; i < dataLength; i++) { + xData[i] = x; + yData[i] = data[i]; + x += pointInterval; + } + series.xIncrement = x; + } else if (isArray(firstPoint)) { // assume all points are arrays + if (valueCount) { // [x, low, high] or [x, o, h, l, c] + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[0]; + yData[i] = pt.slice(1, valueCount + 1); + } + } else { // [x, y] + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[0]; + yData[i] = pt[1]; + } + } + } + /* else { + error(12); // Highcharts expects configs to be numbers or arrays in turbo mode + }*/ + } else { + for (i = 0; i < dataLength; i++) { + pt = { series: series }; + pointProto.applyOptions.apply(pt, [data[i]]); + xData[i] = pt.x; + yData[i] = pointProto.toYData ? pointProto.toYData.apply(pt) : pt.y; + } + } + + series.data = []; + series.options.data = data; + series.xData = xData; + series.yData = yData; + + // destroy old points + i = (oldData && oldData.length) || 0; + while (i--) { + if (oldData[i] && oldData[i].destroy) { + oldData[i].destroy(); + } + } + + // reset minRange (#878) + if (xAxis) { + xAxis.minRange = xAxis.userMinRange; + } + + // redraw + series.isDirty = series.isDirtyData = chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(false); + } + }, + + /** + * Remove a series and optionally redraw the chart + * + * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + */ + + remove: function (redraw, animation) { + var series = this, + chart = series.chart; + redraw = pick(redraw, true); + + if (!series.isRemoving) { /* prevent triggering native event in jQuery + (calling the remove function from the remove event) */ + series.isRemoving = true; + + // fire the event with a default handler of removing the point + fireEvent(series, 'remove', null, function () { + + + // destroy elements + series.destroy(); + + + // redraw + chart.isDirtyLegend = chart.isDirtyBox = true; + if (redraw) { + chart.redraw(animation); + } + }); + + } + series.isRemoving = false; + }, + + /** + * Process the data by cropping away unused data points if the series is longer + * than the crop threshold. This saves computing time for lage series. + */ + processData: function (force) { + var series = this, + processedXData = series.xData, // copied during slice operation below + processedYData = series.yData, + dataLength = processedXData.length, + cropStart = 0, + cropEnd = dataLength, + cropped, + distance, + closestPointRange, + xAxis = series.xAxis, + i, // loop variable + options = series.options, + cropThreshold = options.cropThreshold, + isCartesian = series.isCartesian; + + // If the series data or axes haven't changed, don't go through this. Return false to pass + // the message on to override methods like in data grouping. + if (isCartesian && !series.isDirty && !xAxis.isDirty && !series.yAxis.isDirty && !force) { + return false; + } + + // optionally filter out points outside the plot area + if (isCartesian && series.sorted && (!cropThreshold || dataLength > cropThreshold || series.forceCrop)) { + var extremes = xAxis.getExtremes(), + min = extremes.min, + max = extremes.max; + + // it's outside current extremes + if (processedXData[dataLength - 1] < min || processedXData[0] > max) { + processedXData = []; + processedYData = []; + + // only crop if it's actually spilling out + } else if (processedXData[0] < min || processedXData[dataLength - 1] > max) { + + // iterate up to find slice start + for (i = 0; i < dataLength; i++) { + if (processedXData[i] >= min) { + cropStart = mathMax(0, i - 1); + break; + } + } + // proceed to find slice end + for (; i < dataLength; i++) { + if (processedXData[i] > max) { + cropEnd = i + 1; + break; + } + + } + processedXData = processedXData.slice(cropStart, cropEnd); + processedYData = processedYData.slice(cropStart, cropEnd); + cropped = true; + } + } + + + // Find the closest distance between processed points + for (i = processedXData.length - 1; i > 0; i--) { + distance = processedXData[i] - processedXData[i - 1]; + if (distance > 0 && (closestPointRange === UNDEFINED || distance < closestPointRange)) { + closestPointRange = distance; + } + } + + // Record the properties + series.cropped = cropped; // undefined or true + series.cropStart = cropStart; + series.processedXData = processedXData; + series.processedYData = processedYData; + + if (options.pointRange === null) { // null means auto, as for columns, candlesticks and OHLC + series.pointRange = closestPointRange || 1; + } + series.closestPointRange = closestPointRange; + + }, + + /** + * Generate the data point after the data has been processed by cropping away + * unused points and optionally grouped in Highcharts Stock. + */ + generatePoints: function () { + var series = this, + options = series.options, + dataOptions = options.data, + data = series.data, + dataLength, + processedXData = series.processedXData, + processedYData = series.processedYData, + pointClass = series.pointClass, + processedDataLength = processedXData.length, + cropStart = series.cropStart || 0, + cursor, + hasGroupedData = series.hasGroupedData, + point, + points = [], + i; + + if (!data && !hasGroupedData) { + var arr = []; + arr.length = dataOptions.length; + data = series.data = arr; + } + + for (i = 0; i < processedDataLength; i++) { + cursor = cropStart + i; + if (!hasGroupedData) { + if (data[cursor]) { + point = data[cursor]; + } else if (dataOptions[cursor] !== UNDEFINED) { // #970 + data[cursor] = point = (new pointClass()).init(series, dataOptions[cursor], processedXData[i]); + } + points[i] = point; + } else { + // splat the y data in case of ohlc data array + points[i] = (new pointClass()).init(series, [processedXData[i]].concat(splat(processedYData[i]))); + } + } + + // Hide cropped-away points - this only runs when the number of points is above cropThreshold, or when + // swithching view from non-grouped data to grouped data (#637) + if (data && (processedDataLength !== (dataLength = data.length) || hasGroupedData)) { + for (i = 0; i < dataLength; i++) { + if (i === cropStart && !hasGroupedData) { // when has grouped data, clear all points + i += processedDataLength; + } + if (data[i]) { + data[i].destroyElements(); + data[i].plotX = UNDEFINED; // #1003 + } + } + } + + series.data = data; + series.points = points; + }, + + /** + * Translate data points from raw data values to chart specific positioning data + * needed later in drawPoints, drawGraph and drawTracker. + */ + translate: function () { + if (!this.processedXData) { // hidden series + this.processData(); + } + this.generatePoints(); + var series = this, + chart = series.chart, + options = series.options, + stacking = options.stacking, + xAxis = series.xAxis, + categories = xAxis.categories, + yAxis = series.yAxis, + points = series.points, + dataLength = points.length, + hasModifyValue = !!series.modifyValue, + isLastSeries, + allStackSeries = yAxis.series, + i = allStackSeries.length; + + // Is it the last visible series? + while (i--) { + if (allStackSeries[i].visible) { + if (i === series.index) { + isLastSeries = true; + } + break; + } + } + + // Translate each point + for (i = 0; i < dataLength; i++) { + var point = points[i], + xValue = point.x, + yValue = point.y, + yBottom = point.low, + stack = yAxis.stacks[(yValue < options.threshold ? '-' : '') + series.stackKey], + pointStack, + pointStackTotal; + + // get the plotX translation + //point.plotX = mathRound(xAxis.translate(xValue, 0, 0, 0, 1) * 10) / 10; // Math.round fixes #591 + point.plotX = xAxis.translate(xValue, 0, 0, 0, 1); // Math.round fixes #591 + + // calculate the bottom y value for stacked series + if (stacking && series.visible && stack && stack[xValue]) { + pointStack = stack[xValue]; + pointStackTotal = pointStack.total; + pointStack.cum = yBottom = pointStack.cum - yValue; // start from top + yValue = yBottom + yValue; + + if (isLastSeries) { + yBottom = options.threshold; + } + + if (stacking === 'percent') { + yBottom = pointStackTotal ? yBottom * 100 / pointStackTotal : 0; + yValue = pointStackTotal ? yValue * 100 / pointStackTotal : 0; + } + + point.percentage = pointStackTotal ? point.y * 100 / pointStackTotal : 0; + point.stackTotal = pointStackTotal; + point.stackY = yValue; + } + + // Set translated yBottom or remove it + point.yBottom = defined(yBottom) ? + yAxis.translate(yBottom, 0, 1, 0, 1) : + null; + + // general hook, used for Highstock compare mode + if (hasModifyValue) { + yValue = series.modifyValue(yValue, point); + } + + // Set the the plotY value, reset it for redraws + point.plotY = (typeof yValue === 'number') ? + mathRound(yAxis.translate(yValue, 0, 1, 0, 1) * 10) / 10 : // Math.round fixes #591 + UNDEFINED; + + // set client related positions for mouse tracking + point.clientX = chart.inverted ? + chart.plotHeight - point.plotX : + point.plotX; // for mouse tracking + + // some API data + point.category = categories && categories[point.x] !== UNDEFINED ? + categories[point.x] : point.x; + + + } + + // now that we have the cropped data, build the segments + series.getSegments(); + }, + /** + * Memoize tooltip texts and positions + */ + setTooltipPoints: function (renew) { + var series = this, + chart = series.chart, + points = [], + pointsLength, + plotSize = chart.plotSizeX, + low, + high, + xAxis = series.xAxis, + point, + i, + tooltipPoints = []; // a lookup array for each pixel in the x dimension + + // don't waste resources if tracker is disabled + if (series.options.enableMouseTracking === false) { + return; + } + + // renew + if (renew) { + series.tooltipPoints = null; + } + + // concat segments to overcome null values + each(series.segments || series.points, function (segment) { + points = points.concat(segment); + }); + + // loop the concatenated points and apply each point to all the closest + // pixel positions + if (xAxis && xAxis.reversed) { + points = points.reverse(); + } + + // Assign each pixel position to the nearest point + pointsLength = points.length; + for (i = 0; i < pointsLength; i++) { + point = points[i]; + low = points[i - 1] ? points[i - 1]._high + 1 : 0; + point._high = high = points[i + 1] ? + mathMax(0, mathFloor((point.plotX + (points[i + 1] ? points[i + 1].plotX : plotSize)) / 2)) : + plotSize; + + while (low >= 0 && low <= high) { + tooltipPoints[low++] = point; + } + } + series.tooltipPoints = tooltipPoints; + }, + + /** + * Format the header of the tooltip + */ + tooltipHeaderFormatter: function (key) { + var series = this, + tooltipOptions = series.tooltipOptions, + xDateFormat = tooltipOptions.xDateFormat, + xAxis = series.xAxis, + isDateTime = xAxis && xAxis.options.type === 'datetime', + n; + + // Guess the best date format based on the closest point distance (#568) + if (isDateTime && !xDateFormat) { + for (n in timeUnits) { + if (timeUnits[n] >= xAxis.closestPointRange) { + xDateFormat = tooltipOptions.dateTimeLabelFormats[n]; + break; + } + } + } + + return tooltipOptions.headerFormat + .replace('{point.key}', isDateTime ? dateFormat(xDateFormat, key) : key) + .replace('{series.name}', series.name) + .replace('{series.color}', series.color); + }, + + /** + * Series mouse over handler + */ + onMouseOver: function () { + var series = this, + chart = series.chart, + hoverSeries = chart.hoverSeries; + + if (!hasTouch && chart.mouseIsDown) { + return; + } + + // set normal state to previous series + if (hoverSeries && hoverSeries !== series) { + hoverSeries.onMouseOut(); + } + + // trigger the event, but to save processing time, + // only if defined + if (series.options.events.mouseOver) { + fireEvent(series, 'mouseOver'); + } + + // hover this + series.setState(HOVER_STATE); + chart.hoverSeries = series; + }, + + /** + * Series mouse out handler + */ + onMouseOut: function () { + // trigger the event only if listeners exist + var series = this, + options = series.options, + chart = series.chart, + tooltip = chart.tooltip, + hoverPoint = chart.hoverPoint; + + // trigger mouse out on the point, which must be in this series + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + + // fire the mouse out event + if (series && options.events.mouseOut) { + fireEvent(series, 'mouseOut'); + } + + + // hide the tooltip + if (tooltip && !options.stickyTracking && !tooltip.shared) { + tooltip.hide(); + } + + // set normal state + series.setState(); + chart.hoverSeries = null; + }, + + /** + * Animate in the series + */ + animate: function (init) { + var series = this, + chart = series.chart, + clipRect = series.clipRect, + animation = series.options.animation; + + if (animation && !isObject(animation)) { + animation = {}; + } + + if (init) { // initialize the animation + if (!clipRect.isAnimating) { // apply it only for one of the series + clipRect.attr('width', 0); + clipRect.isAnimating = true; + } + + } else { // run the animation + clipRect.animate({ + width: chart.plotSizeX + }, animation); + + // delete this function to allow it only once + this.animate = null; + } + }, + + + /** + * Draw the markers + */ + drawPoints: function () { + var series = this, + pointAttr, + points = series.points, + chart = series.chart, + plotX, + plotY, + i, + point, + radius, + symbol, + isImage, + graphic; + + if (series.options.marker.enabled) { + i = points.length; + while (i--) { + point = points[i]; + plotX = point.plotX; + plotY = point.plotY; + graphic = point.graphic; + + // only draw the point if y is defined + if (plotY !== UNDEFINED && !isNaN(plotY)) { + + // shortcuts + pointAttr = point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE]; + radius = pointAttr.r; + symbol = pick(point.marker && point.marker.symbol, series.symbol); + isImage = symbol.indexOf('url') === 0; + + if (graphic) { // update + graphic.animate(extend({ + x: plotX - radius, + y: plotY - radius + }, graphic.symbolName ? { // don't apply to image symbols #507 + width: 2 * radius, + height: 2 * radius + } : {})); + } else if (radius > 0 || isImage) { + point.graphic = chart.renderer.symbol( + symbol, + plotX - radius, + plotY - radius, + 2 * radius, + 2 * radius + ) + .attr(pointAttr) + .add(series.group); + } + } + } + } + + }, + + /** + * Convert state properties from API naming conventions to SVG attributes + * + * @param {Object} options API options object + * @param {Object} base1 SVG attribute object to inherit from + * @param {Object} base2 Second level SVG attribute object to inherit from + */ + convertAttribs: function (options, base1, base2, base3) { + var conversion = this.pointAttrToOptions, + attr, + option, + obj = {}; + + options = options || {}; + base1 = base1 || {}; + base2 = base2 || {}; + base3 = base3 || {}; + + for (attr in conversion) { + option = conversion[attr]; + obj[attr] = pick(options[option], base1[attr], base2[attr], base3[attr]); + } + return obj; + }, + + /** + * Get the state attributes. Each series type has its own set of attributes + * that are allowed to change on a point's state change. Series wide attributes are stored for + * all series, and additionally point specific attributes are stored for all + * points with individual marker options. If such options are not defined for the point, + * a reference to the series wide attributes is stored in point.pointAttr. + */ + getAttribs: function () { + var series = this, + normalOptions = defaultPlotOptions[series.type].marker ? series.options.marker : series.options, + stateOptions = normalOptions.states, + stateOptionsHover = stateOptions[HOVER_STATE], + pointStateOptionsHover, + seriesColor = series.color, + normalDefaults = { + stroke: seriesColor, + fill: seriesColor + }, + points = series.points || [], // #927 + i, + point, + seriesPointAttr = [], + pointAttr, + pointAttrToOptions = series.pointAttrToOptions, + hasPointSpecificOptions, + key; + + // series type specific modifications + if (series.options.marker) { // line, spline, area, areaspline, scatter + + // if no hover radius is given, default to normal radius + 2 + stateOptionsHover.radius = stateOptionsHover.radius || normalOptions.radius + 2; + stateOptionsHover.lineWidth = stateOptionsHover.lineWidth || normalOptions.lineWidth + 1; + + } else { // column, bar, pie + + // if no hover color is given, brighten the normal color + stateOptionsHover.color = stateOptionsHover.color || + Color(stateOptionsHover.color || seriesColor) + .brighten(stateOptionsHover.brightness).get(); + } + + // general point attributes for the series normal state + seriesPointAttr[NORMAL_STATE] = series.convertAttribs(normalOptions, normalDefaults); + + // HOVER_STATE and SELECT_STATE states inherit from normal state except the default radius + each([HOVER_STATE, SELECT_STATE], function (state) { + seriesPointAttr[state] = + series.convertAttribs(stateOptions[state], seriesPointAttr[NORMAL_STATE]); + }); + + // set it + series.pointAttr = seriesPointAttr; + + + // Generate the point-specific attribute collections if specific point + // options are given. If not, create a referance to the series wide point + // attributes + i = points.length; + while (i--) { + point = points[i]; + normalOptions = (point.options && point.options.marker) || point.options; + if (normalOptions && normalOptions.enabled === false) { + normalOptions.radius = 0; + } + hasPointSpecificOptions = false; + + // check if the point has specific visual options + if (point.options) { + for (key in pointAttrToOptions) { + if (defined(normalOptions[pointAttrToOptions[key]])) { + hasPointSpecificOptions = true; + } + } + } + + + // a specific marker config object is defined for the individual point: + // create it's own attribute collection + if (hasPointSpecificOptions) { + + pointAttr = []; + stateOptions = normalOptions.states || {}; // reassign for individual point + pointStateOptionsHover = stateOptions[HOVER_STATE] = stateOptions[HOVER_STATE] || {}; + + // if no hover color is given, brighten the normal color + if (!series.options.marker) { // column, bar, point + pointStateOptionsHover.color = + Color(pointStateOptionsHover.color || point.options.color) + .brighten(pointStateOptionsHover.brightness || + stateOptionsHover.brightness).get(); + + } + + // normal point state inherits series wide normal state + pointAttr[NORMAL_STATE] = series.convertAttribs(normalOptions, seriesPointAttr[NORMAL_STATE]); + + // inherit from point normal and series hover + pointAttr[HOVER_STATE] = series.convertAttribs( + stateOptions[HOVER_STATE], + seriesPointAttr[HOVER_STATE], + pointAttr[NORMAL_STATE] + ); + // inherit from point normal and series hover + pointAttr[SELECT_STATE] = series.convertAttribs( + stateOptions[SELECT_STATE], + seriesPointAttr[SELECT_STATE], + pointAttr[NORMAL_STATE] + ); + + + // no marker config object is created: copy a reference to the series-wide + // attribute collection + } else { + pointAttr = seriesPointAttr; + } + + point.pointAttr = pointAttr; + + } + + }, + + + /** + * Clear DOM objects and free up memory + */ + destroy: function () { + var series = this, + chart = series.chart, + seriesClipRect = series.clipRect, + issue134 = /AppleWebKit\/533/.test(userAgent), + destroy, + i, + data = series.data || [], + point, + prop, + axis; + + // add event hook + fireEvent(series, 'destroy'); + + // remove all events + removeEvent(series); + + // erase from axes + each(['xAxis', 'yAxis'], function (AXIS) { + axis = series[AXIS]; + if (axis) { + erase(axis.series, series); + axis.isDirty = true; + } + }); + + // remove legend items + if (series.legendItem) { + series.chart.legend.destroyItem(series); + } + + // destroy all points with their elements + i = data.length; + while (i--) { + point = data[i]; + if (point && point.destroy) { + point.destroy(); + } + } + series.points = null; + + // If this series clipRect is not the global one (which is removed on chart.destroy) we + // destroy it here. + if (seriesClipRect && seriesClipRect !== chart.clipRect) { + series.clipRect = seriesClipRect.destroy(); + } + + // destroy all SVGElements associated to the series + each(['area', 'graph', 'dataLabelsGroup', 'group', 'tracker', 'trackerGroup'], function (prop) { + if (series[prop]) { + + // issue 134 workaround + destroy = issue134 && prop === 'group' ? + 'hide' : + 'destroy'; + + series[prop][destroy](); + } + }); + + // remove from hoverSeries + if (chart.hoverSeries === series) { + chart.hoverSeries = null; + } + erase(chart.series, series); + + // clear all members + for (prop in series) { + delete series[prop]; + } + }, + + /** + * Draw the data labels + */ + drawDataLabels: function () { + + var series = this, + seriesOptions = series.options, + options = seriesOptions.dataLabels; + + if (options.enabled || series._hasPointLabels) { + var x, + y, + points = series.points, + pointOptions, + generalOptions, + str, + dataLabelsGroup = series.dataLabelsGroup, + chart = series.chart, + xAxis = series.xAxis, + groupLeft = xAxis ? xAxis.left : chart.plotLeft, + yAxis = series.yAxis, + groupTop = yAxis ? yAxis.top : chart.plotTop, + renderer = chart.renderer, + inverted = chart.inverted, + seriesType = series.type, + stacking = seriesOptions.stacking, + isBarLike = seriesType === 'column' || seriesType === 'bar', + vAlignIsNull = options.verticalAlign === null, + yIsNull = options.y === null, + fontMetrics = renderer.fontMetrics(options.style.fontSize), // height and baseline + fontLineHeight = fontMetrics.h, + fontBaseline = fontMetrics.b, + dataLabel, + enabled; + + if (isBarLike) { + var defaultYs = { + top: fontBaseline, + middle: fontBaseline - fontLineHeight / 2, + bottom: -fontLineHeight + fontBaseline + }; + if (stacking) { + // In stacked series the default label placement is inside the bars + if (vAlignIsNull) { + options = merge(options, {verticalAlign: 'middle'}); + } + + // If no y delta is specified, try to create a good default + if (yIsNull) { + options = merge(options, { y: defaultYs[options.verticalAlign]}); + } + } else { + // In non stacked series the default label placement is on top of the bars + if (vAlignIsNull) { + options = merge(options, {verticalAlign: 'top'}); + + // If no y delta is specified, try to create a good default (like default bar) + } else if (yIsNull) { + options = merge(options, { y: defaultYs[options.verticalAlign]}); + } + + } + } + + + // create a separate group for the data labels to avoid rotation + if (!dataLabelsGroup) { + dataLabelsGroup = series.dataLabelsGroup = + renderer.g('data-labels') + .attr({ + visibility: series.visible ? VISIBLE : HIDDEN, + zIndex: 6 + }) + .translate(groupLeft, groupTop) + .add(); + } else { + dataLabelsGroup.translate(groupLeft, groupTop); + } + + // make the labels for each point + generalOptions = options; + each(points, function (point) { + + dataLabel = point.dataLabel; + + // Merge in individual options from point + options = generalOptions; // reset changes from previous points + pointOptions = point.options; + if (pointOptions && pointOptions.dataLabels) { + options = merge(options, pointOptions.dataLabels); + } + enabled = options.enabled; + + // Get the positions + if (enabled) { + var plotX = (point.barX && point.barX + point.barW / 2) || pick(point.plotX, -999), + plotY = pick(point.plotY, -999), + + // if options.y is null, which happens by default on column charts, set the position + // above or below the column depending on the threshold + individualYDelta = options.y === null ? + (point.y >= seriesOptions.threshold ? + -fontLineHeight + fontBaseline : // below the threshold + fontBaseline) : // above the threshold + options.y; + + x = (inverted ? chart.plotWidth - plotY : plotX) + options.x; + y = mathRound((inverted ? chart.plotHeight - plotX : plotY) + individualYDelta); + + } + + // If the point is outside the plot area, destroy it. #678, #820 + if (dataLabel && series.isCartesian && (!chart.isInsidePlot(x, y) || !enabled)) { + point.dataLabel = dataLabel.destroy(); + + // Individual labels are disabled if the are explicitly disabled + // in the point options, or if they fall outside the plot area. + } else if (enabled) { + + var align = options.align, + attr, + name; + + // Get the string + str = options.formatter.call(point.getLabelConfig(), options); + + // in columns, align the string to the column + if (seriesType === 'column') { + x += { left: -1, right: 1 }[align] * point.barW / 2 || 0; + } + + if (!stacking && inverted && point.y < 0) { + align = 'right'; + x -= 10; + } + + // Determine the color + options.style.color = pick(options.color, options.style.color, series.color, 'black'); + + + // update existing label + if (dataLabel) { + // vertically centered + dataLabel + .attr({ + text: str + }).animate({ + x: x, + y: y + }); + // create new label + } else if (defined(str)) { + attr = { + align: align, + fill: options.backgroundColor, + stroke: options.borderColor, + 'stroke-width': options.borderWidth, + r: options.borderRadius || 0, + rotation: options.rotation, + padding: options.padding, + zIndex: 1 + }; + // Remove unused attributes (#947) + for (name in attr) { + if (attr[name] === UNDEFINED) { + delete attr[name]; + } + } + + dataLabel = point.dataLabel = renderer[options.rotation ? 'text' : 'label']( // labels don't support rotation + str, + x, + y, + null, + null, + null, + options.useHTML, + true // baseline for backwards compat + ) + .attr(attr) + .css(options.style) + .add(dataLabelsGroup) + .shadow(options.shadow); + } + + if (isBarLike && seriesOptions.stacking && dataLabel) { + var barX = point.barX, + barY = point.barY, + barW = point.barW, + barH = point.barH; + + dataLabel.align(options, null, + { + x: inverted ? chart.plotWidth - barY - barH : barX, + y: inverted ? chart.plotHeight - barX - barW : barY, + width: inverted ? barH : barW, + height: inverted ? barW : barH + }); + } + + + } + }); + } + }, + + /** + * Return the graph path of a segment + */ + getSegmentPath: function (segment) { + var series = this, + segmentPath = []; + + // build the segment line + each(segment, function (point, i) { + + if (series.getPointSpline) { // generate the spline as defined in the SplineSeries object + segmentPath.push.apply(segmentPath, series.getPointSpline(segment, point, i)); + + } else { + + // moveTo or lineTo + segmentPath.push(i ? L : M); + + // step line? + if (i && series.options.step) { + var lastPoint = segment[i - 1]; + segmentPath.push( + point.plotX, + lastPoint.plotY + ); + } + + // normal line to next point + segmentPath.push( + point.plotX, + point.plotY + ); + } + }); + + return segmentPath; + }, + + /** + * Draw the actual graph + */ + drawGraph: function () { + var series = this, + options = series.options, + chart = series.chart, + graph = series.graph, + graphPath = [], + group = series.group, + color = options.lineColor || series.color, + lineWidth = options.lineWidth, + dashStyle = options.dashStyle, + segmentPath, + renderer = chart.renderer, + singlePoints = [], // used in drawTracker + attribs; + + // divide into segments and build graph and area paths + each(series.segments, function (segment) { + + segmentPath = series.getSegmentPath(segment); + + // add the segment to the graph, or a single point for tracking + if (segment.length > 1) { + graphPath = graphPath.concat(segmentPath); + } else { + singlePoints.push(segment[0]); + } + }); + + // used in drawTracker: + series.graphPath = graphPath; + series.singlePoints = singlePoints; + + // draw the graph + if (graph) { + stop(graph); // cancel running animations, #459 + graph.animate({ d: graphPath }); + + } else { + if (lineWidth) { + attribs = { + stroke: color, + 'stroke-width': lineWidth + }; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + + series.graph = renderer.path(graphPath) + .attr(attribs).add(group).shadow(options.shadow); + } + } + }, + + /** + * Initialize and perform group inversion on series.group and series.trackerGroup + */ + invertGroups: function () { + var series = this, + group = series.group, + trackerGroup = series.trackerGroup, + chart = series.chart; + + // A fixed size is needed for inversion to work + function setInvert() { + var size = { + width: series.yAxis.len, + height: series.xAxis.len + }; + + // Set the series.group size + group.attr(size).invert(); + + // Set the tracker group size + if (trackerGroup) { + trackerGroup.attr(size).invert(); + } + } + + addEvent(chart, 'resize', setInvert); // do it on resize + addEvent(series, 'destroy', function () { + removeEvent(chart, 'resize', setInvert); + }); + + // Do it now + setInvert(); // do it now + + // On subsequent render and redraw, just do setInvert without setting up events again + series.invertGroups = setInvert; + }, + + /** + * Create the series group + */ + createGroup: function () { + + var chart = this.chart, + group = this.group = chart.renderer.g('series'); + + group.attr({ + visibility: this.visible ? VISIBLE : HIDDEN, + zIndex: this.options.zIndex + }) + .translate(this.xAxis.left, this.yAxis.top) + .add(chart.seriesGroup); + + // Only run this once + this.createGroup = noop; + }, + + /** + * Render the graph and markers + */ + render: function () { + var series = this, + chart = series.chart, + group, + options = series.options, + doClip = options.clip !== false, + animation = options.animation, + doAnimation = animation && series.animate, + duration = doAnimation ? (animation && animation.duration) || 500 : 0, + clipRect = series.clipRect, + renderer = chart.renderer; + + + // Add plot area clipping rectangle. If this is before chart.hasRendered, + // create one shared clipRect. + + // Todo: since creating the clip property, the clipRect is created but + // never used when clip is false. A better way would be that the animation + // would run, then the clipRect destroyed. + if (!clipRect) { + clipRect = series.clipRect = !chart.hasRendered && chart.clipRect ? + chart.clipRect : + renderer.clipRect(0, 0, chart.plotSizeX, chart.plotSizeY + 1); + if (!chart.clipRect) { + chart.clipRect = clipRect; + } + } + + + // the group + series.createGroup(); + group = series.group; + + + series.drawDataLabels(); + + // initiate the animation + if (doAnimation) { + series.animate(true); + } + + // cache attributes for shapes + series.getAttribs(); + + // draw the graph if any + if (series.drawGraph) { + series.drawGraph(); + } + + // draw the points + series.drawPoints(); + + // draw the mouse tracking area + if (series.options.enableMouseTracking !== false) { + series.drawTracker(); + } + + // Handle inverted series and tracker groups + if (chart.inverted) { + series.invertGroups(); + } + + // Do the initial clipping. This must be done after inverting for VML. + if (doClip && !series.hasRendered) { + group.clip(clipRect); + if (series.trackerGroup) { + series.trackerGroup.clip(chart.clipRect); + } + } + + + // run the animation + if (doAnimation) { + series.animate(); + } + + // finish the individual clipRect + setTimeout(function () { + clipRect.isAnimating = false; + group = series.group; // can be destroyed during the timeout + if (group && clipRect !== chart.clipRect && clipRect.renderer) { + if (doClip) { + group.clip((series.clipRect = chart.clipRect)); + } + clipRect.destroy(); + } + }, duration); + + series.isDirty = series.isDirtyData = false; // means data is in accordance with what you see + // (See #322) series.isDirty = series.isDirtyData = false; // means data is in accordance with what you see + series.hasRendered = true; + }, + + /** + * Redraw the series after an update in the axes. + */ + redraw: function () { + var series = this, + chart = series.chart, + wasDirtyData = series.isDirtyData, // cache it here as it is set to false in render, but used after + group = series.group; + + // reposition on resize + if (group) { + if (chart.inverted) { + group.attr({ + width: chart.plotWidth, + height: chart.plotHeight + }); + } + + group.animate({ + translateX: series.xAxis.left, + translateY: series.yAxis.top + }); + } + + series.translate(); + series.setTooltipPoints(true); + + series.render(); + if (wasDirtyData) { + fireEvent(series, 'updatedData'); + } + }, + + /** + * Set the state of the graph + */ + setState: function (state) { + var series = this, + options = series.options, + graph = series.graph, + stateOptions = options.states, + lineWidth = options.lineWidth; + + state = state || NORMAL_STATE; + + if (series.state !== state) { + series.state = state; + + if (stateOptions[state] && stateOptions[state].enabled === false) { + return; + } + + if (state) { + lineWidth = stateOptions[state].lineWidth || lineWidth + 1; + } + + if (graph && !graph.dashstyle) { // hover is turned off for dashed lines in VML + graph.attr({ // use attr because animate will cause any other animation on the graph to stop + 'stroke-width': lineWidth + }, state ? 0 : 500); + } + } + }, + + /** + * Set the visibility of the graph + * + * @param vis {Boolean} True to show the series, false to hide. If UNDEFINED, + * the visibility is toggled. + */ + setVisible: function (vis, redraw) { + var series = this, + chart = series.chart, + legendItem = series.legendItem, + seriesGroup = series.group, + seriesTracker = series.tracker, + dataLabelsGroup = series.dataLabelsGroup, + showOrHide, + i, + points = series.points, + point, + ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries, + oldVisibility = series.visible; + + // if called without an argument, toggle visibility + series.visible = vis = vis === UNDEFINED ? !oldVisibility : vis; + showOrHide = vis ? 'show' : 'hide'; + + // show or hide series + if (seriesGroup) { // pies don't have one + seriesGroup[showOrHide](); + } + + // show or hide trackers + if (seriesTracker) { + seriesTracker[showOrHide](); + } else if (points) { + i = points.length; + while (i--) { + point = points[i]; + if (point.tracker) { + point.tracker[showOrHide](); + } + } + } + + + if (dataLabelsGroup) { + dataLabelsGroup[showOrHide](); + } + + if (legendItem) { + chart.legend.colorizeItem(series, vis); + } + + + // rescale or adapt to resized chart + series.isDirty = true; + // in a stack, all other series are affected + if (series.options.stacking) { + each(chart.series, function (otherSeries) { + if (otherSeries.options.stacking && otherSeries.visible) { + otherSeries.isDirty = true; + } + }); + } + + if (ignoreHiddenSeries) { + chart.isDirtyBox = true; + } + if (redraw !== false) { + chart.redraw(); + } + + fireEvent(series, showOrHide); + }, + + /** + * Show the graph + */ + show: function () { + this.setVisible(true); + }, + + /** + * Hide the graph + */ + hide: function () { + this.setVisible(false); + }, + + + /** + * Set the selected state of the graph + * + * @param selected {Boolean} True to select the series, false to unselect. If + * UNDEFINED, the selection state is toggled. + */ + select: function (selected) { + var series = this; + // if called without an argument, toggle + series.selected = selected = (selected === UNDEFINED) ? !series.selected : selected; + + if (series.checkbox) { + series.checkbox.checked = selected; + } + + fireEvent(series, selected ? 'select' : 'unselect'); + }, + + /** + * Create a group that holds the tracking object or objects. This allows for + * individual clipping and placement of each series tracker. + */ + drawTrackerGroup: function () { + var trackerGroup = this.trackerGroup, + chart = this.chart; + + if (this.isCartesian) { + + // Generate it on first call + if (!trackerGroup) { + this.trackerGroup = trackerGroup = chart.renderer.g() + .attr({ + zIndex: this.options.zIndex || 1 + }) + .add(chart.trackerGroup); + + } + // Place it on first and subsequent (redraw) calls + trackerGroup.translate(this.xAxis.left, this.yAxis.top); + + } + + return trackerGroup; + }, + + /** + * Draw the tracker object that sits above all data labels and markers to + * track mouse events on the graph or points. For the line type charts + * the tracker uses the same graphPath, but with a greater stroke width + * for better control. + */ + drawTracker: function () { + var series = this, + options = series.options, + trackByArea = options.trackByArea, + trackerPath = [].concat(trackByArea ? series.areaPath : series.graphPath), + trackerPathLength = trackerPath.length, + chart = series.chart, + renderer = chart.renderer, + snap = chart.options.tooltip.snap, + tracker = series.tracker, + cursor = options.cursor, + css = cursor && { cursor: cursor }, + singlePoints = series.singlePoints, + trackerGroup = series.drawTrackerGroup(), + singlePoint, + i; + + // Extend end points. A better way would be to use round linecaps, + // but those are not clickable in VML. + if (trackerPathLength && !trackByArea) { + i = trackerPathLength + 1; + while (i--) { + if (trackerPath[i] === M) { // extend left side + trackerPath.splice(i + 1, 0, trackerPath[i + 1] - snap, trackerPath[i + 2], L); + } + if ((i && trackerPath[i] === M) || i === trackerPathLength) { // extend right side + trackerPath.splice(i, 0, L, trackerPath[i - 2] + snap, trackerPath[i - 1]); + } + } + } + + // handle single points + for (i = 0; i < singlePoints.length; i++) { + singlePoint = singlePoints[i]; + trackerPath.push(M, singlePoint.plotX - snap, singlePoint.plotY, + L, singlePoint.plotX + snap, singlePoint.plotY); + } + + + // draw the tracker + if (tracker) { + tracker.attr({ d: trackerPath }); + + } else { // create + + series.tracker = renderer.path(trackerPath) + .attr({ + isTracker: true, + 'stroke-linejoin': 'bevel', + visibility: series.visible ? VISIBLE : HIDDEN, + stroke: TRACKER_FILL, + fill: trackByArea ? TRACKER_FILL : NONE, + 'stroke-width': options.lineWidth + (trackByArea ? 0 : 2 * snap) + }) + .on(hasTouch ? 'touchstart' : 'mouseover', function () { + if (chart.hoverSeries !== series) { + series.onMouseOver(); + } + }) + .on('mouseout', function () { + if (!options.stickyTracking) { + series.onMouseOut(); + } + }) + .css(css) + .add(trackerGroup); + } + + } + + }; // end Series prototype + + + /** + * LineSeries object + */ + var LineSeries = extendClass(Series); + seriesTypes.line = LineSeries; + + /** + * Set the default options for area + */ + defaultPlotOptions.area = merge(defaultSeriesOptions, { + threshold: 0 + // trackByArea: false, + // lineColor: null, // overrides color, but lets fillColor be unaltered + // fillOpacity: 0.75, + // fillColor: null + }); + + /** + * AreaSeries object + */ + var AreaSeries = extendClass(Series, { + type: 'area', + + /** + * Extend the base Series getSegmentPath method by adding the path for the area. + * This path is pushed to the series.areaPath property. + */ + getSegmentPath: function (segment) { + + var segmentPath = Series.prototype.getSegmentPath.call(this, segment), // call base method + areaSegmentPath = [].concat(segmentPath), // work on a copy for the area path + i, + options = this.options, + segLength = segmentPath.length, + translatedThreshold = this.yAxis.getThreshold(options.threshold); + + if (segLength === 3) { // for animation from 1 to two points + areaSegmentPath.push(L, segmentPath[1], segmentPath[2]); + } + if (options.stacking && this.type !== 'areaspline') { + + // Follow stack back. Todo: implement areaspline. A general solution could be to + // reverse the entire graphPath of the previous series, though may be hard with + // splines and with series with different extremes + for (i = segment.length - 1; i >= 0; i--) { + + // step line? + if (i < segment.length - 1 && options.step) { + areaSegmentPath.push(segment[i + 1].plotX, segment[i].yBottom); + } + + areaSegmentPath.push(segment[i].plotX, segment[i].yBottom); + } + + } else { // follow zero line back + areaSegmentPath.push( + L, + segment[segment.length - 1].plotX, + translatedThreshold, + L, + segment[0].plotX, + translatedThreshold + ); + } + this.areaPath = this.areaPath.concat(areaSegmentPath); + + return segmentPath; + }, + + /** + * Draw the graph and the underlying area. This method calls the Series base + * function and adds the area. The areaPath is calculated in the getSegmentPath + * method called from Series.prototype.drawGraph. + */ + drawGraph: function () { + + // Define or reset areaPath + this.areaPath = []; + + // Call the base method + Series.prototype.drawGraph.apply(this); + + // Define local variables + var areaPath = this.areaPath, + options = this.options, + area = this.area; + + // Create or update the area + if (area) { // update + area.animate({ d: areaPath }); + + } else { // create + this.area = this.chart.renderer.path(areaPath) + .attr({ + fill: pick( + options.fillColor, + Color(this.color).setOpacity(options.fillOpacity || 0.75).get() + ) + }).add(this.group); + } + }, + + /** + * Get the series' symbol in the legend + * + * @param {Object} legend The legend object + * @param {Object} item The series (this) or point + */ + drawLegendSymbol: function (legend, item) { + + item.legendSymbol = this.chart.renderer.rect( + 0, + legend.baseline - 11, + legend.options.symbolWidth, + 12, + 2 + ).attr({ + zIndex: 3 + }).add(item.legendGroup); + + } + }); + + seriesTypes.area = AreaSeries; + /** + * Set the default options for spline + */ + defaultPlotOptions.spline = merge(defaultSeriesOptions); + + /** + * SplineSeries object + */ + var SplineSeries = extendClass(Series, { + type: 'spline', + + /** + * Draw the actual graph + */ + getPointSpline: function (segment, point, i) { + var smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc + denom = smoothing + 1, + plotX = point.plotX, + plotY = point.plotY, + lastPoint = segment[i - 1], + nextPoint = segment[i + 1], + leftContX, + leftContY, + rightContX, + rightContY, + ret; + + // find control points + if (i && i < segment.length - 1) { + var lastX = lastPoint.plotX, + lastY = lastPoint.plotY, + nextX = nextPoint.plotX, + nextY = nextPoint.plotY, + correction; + + leftContX = (smoothing * plotX + lastX) / denom; + leftContY = (smoothing * plotY + lastY) / denom; + rightContX = (smoothing * plotX + nextX) / denom; + rightContY = (smoothing * plotY + nextY) / denom; + + // have the two control points make a straight line through main point + correction = ((rightContY - leftContY) * (rightContX - plotX)) / + (rightContX - leftContX) + plotY - rightContY; + + leftContY += correction; + rightContY += correction; + + // to prevent false extremes, check that control points are between + // neighbouring points' y values + if (leftContY > lastY && leftContY > plotY) { + leftContY = mathMax(lastY, plotY); + rightContY = 2 * plotY - leftContY; // mirror of left control point + } else if (leftContY < lastY && leftContY < plotY) { + leftContY = mathMin(lastY, plotY); + rightContY = 2 * plotY - leftContY; + } + if (rightContY > nextY && rightContY > plotY) { + rightContY = mathMax(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } else if (rightContY < nextY && rightContY < plotY) { + rightContY = mathMin(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } + + // record for drawing in next point + point.rightContX = rightContX; + point.rightContY = rightContY; + + } + + // moveTo or lineTo + if (!i) { + ret = [M, plotX, plotY]; + } else { // curve from last point to this + ret = [ + 'C', + lastPoint.rightContX || lastPoint.plotX, + lastPoint.rightContY || lastPoint.plotY, + leftContX || plotX, + leftContY || plotY, + plotX, + plotY + ]; + lastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later + } + return ret; + } + }); + seriesTypes.spline = SplineSeries; + + /** + * Set the default options for areaspline + */ + defaultPlotOptions.areaspline = merge(defaultPlotOptions.area); + + /** + * AreaSplineSeries object + */ + var areaProto = AreaSeries.prototype, + AreaSplineSeries = extendClass(SplineSeries, { + type: 'areaspline', + + // Mix in methods from the area series + getSegmentPath: areaProto.getSegmentPath, + drawGraph: areaProto.drawGraph + }); + seriesTypes.areaspline = AreaSplineSeries; + + /** + * Set the default options for column + */ + defaultPlotOptions.column = merge(defaultSeriesOptions, { + borderColor: '#FFFFFF', + borderWidth: 1, + borderRadius: 0, + //colorByPoint: undefined, + groupPadding: 0.2, + marker: null, // point options are specified in the base options + pointPadding: 0.1, + //pointWidth: null, + minPointLength: 0, + cropThreshold: 50, // when there are more points, they will not animate out of the chart on xAxis.setExtremes + pointRange: null, // null means auto, meaning 1 in a categorized axis and least distance between points if not categories + states: { + hover: { + brightness: 0.1, + shadow: false + }, + select: { + color: '#C0C0C0', + borderColor: '#000000', + shadow: false + } + }, + dataLabels: { + y: null, + verticalAlign: null + }, + threshold: 0 + }); + + /** + * ColumnSeries object + */ + var ColumnSeries = extendClass(Series, { + type: 'column', + tooltipOutsidePlot: true, + pointAttrToOptions: { // mapping between SVG attributes and the corresponding options + stroke: 'borderColor', + 'stroke-width': 'borderWidth', + fill: 'color', + r: 'borderRadius' + }, + init: function () { + Series.prototype.init.apply(this, arguments); + + var series = this, + chart = series.chart; + + // if the series is added dynamically, force redraw of other + // series affected by a new column + if (chart.hasRendered) { + each(chart.series, function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + }, + + /** + * Translate each point to the plot area coordinate system and find shape positions + */ + translate: function () { + var series = this, + chart = series.chart, + options = series.options, + stacking = options.stacking, + borderWidth = options.borderWidth, + columnCount = 0, + xAxis = series.xAxis, + reversedXAxis = xAxis.reversed, + stackGroups = {}, + stackKey, + columnIndex; + + Series.prototype.translate.apply(series); + + // Get the total number of column type series. + // This is called on every series. Consider moving this logic to a + // chart.orderStacks() function and call it on init, addSeries and removeSeries + each(chart.series, function (otherSeries) { + if (otherSeries.type === series.type && otherSeries.visible && + series.options.group === otherSeries.options.group) { // used in Stock charts navigator series + if (otherSeries.options.stacking) { + stackKey = otherSeries.stackKey; + if (stackGroups[stackKey] === UNDEFINED) { + stackGroups[stackKey] = columnCount++; + } + columnIndex = stackGroups[stackKey]; + } else { + columnIndex = columnCount++; + } + otherSeries.columnIndex = columnIndex; + } + }); + + // calculate the width and position of each column based on + // the number of column series in the plot, the groupPadding + // and the pointPadding options + var points = series.points, + categoryWidth = mathAbs(xAxis.transA) * (xAxis.ordinalSlope || options.pointRange || xAxis.closestPointRange || 1), + groupPadding = categoryWidth * options.groupPadding, + groupWidth = categoryWidth - 2 * groupPadding, + pointOffsetWidth = groupWidth / columnCount, + optionPointWidth = options.pointWidth, + pointPadding = defined(optionPointWidth) ? (pointOffsetWidth - optionPointWidth) / 2 : + pointOffsetWidth * options.pointPadding, + pointWidth = pick(optionPointWidth, pointOffsetWidth - 2 * pointPadding), // exact point width, used in polar charts + barW = mathCeil(mathMax(pointWidth, 1 + 2 * borderWidth)), // rounded and postprocessed for border width + colIndex = (reversedXAxis ? columnCount - + series.columnIndex : series.columnIndex) || 0, + pointXOffset = pointPadding + (groupPadding + colIndex * + pointOffsetWidth - (categoryWidth / 2)) * + (reversedXAxis ? -1 : 1), + threshold = options.threshold, + translatedThreshold = series.yAxis.getThreshold(threshold), + minPointLength = pick(options.minPointLength, 5); + + // record the new values + each(points, function (point) { + var plotY = point.plotY, + yBottom = pick(point.yBottom, translatedThreshold), + barX = point.plotX + pointXOffset, + barY = mathCeil(mathMin(plotY, yBottom)), + barH = mathCeil(mathMax(plotY, yBottom) - barY), + stack = series.yAxis.stacks[(point.y < 0 ? '-' : '') + series.stackKey], + shapeArgs; + + // Record the offset'ed position and width of the bar to be able to align the stacking total correctly + if (stacking && series.visible && stack && stack[point.x]) { + stack[point.x].setOffset(pointXOffset, barW); + } + + // handle options.minPointLength + if (mathAbs(barH) < minPointLength) { + if (minPointLength) { + barH = minPointLength; + barY = + mathAbs(barY - translatedThreshold) > minPointLength ? // stacked + yBottom - minPointLength : // keep position + translatedThreshold - (plotY <= translatedThreshold ? minPointLength : 0); + } + } + + extend(point, { + barX: barX, + barY: barY, + barW: barW, + barH: barH, + pointWidth: pointWidth + }); + + // create shape type and shape args that are reused in drawPoints and drawTracker + point.shapeType = 'rect'; + point.shapeArgs = shapeArgs = chart.renderer.Element.prototype.crisp.call(0, borderWidth, barX, barY, barW, barH); + + if (borderWidth % 2) { // correct for shorting in crisp method, visible in stacked columns with 1px border + shapeArgs.y -= 1; + shapeArgs.height += 1; + } + + // make small columns responsive to mouse + point.trackerArgs = mathAbs(barH) < 3 && merge(point.shapeArgs, { + height: 6, + y: barY - 3 + }); + }); + + }, + + getSymbol: function () { + }, + + /** + * Use a solid rectangle like the area series types + */ + drawLegendSymbol: AreaSeries.prototype.drawLegendSymbol, + + + /** + * Columns have no graph + */ + drawGraph: function () { + }, + + /** + * Draw the columns. For bars, the series.group is rotated, so the same coordinates + * apply for columns and bars. This method is inherited by scatter series. + * + */ + drawPoints: function () { + var series = this, + options = series.options, + renderer = series.chart.renderer, + graphic, + shapeArgs; + + + // draw the columns + each(series.points, function (point) { + var plotY = point.plotY; + if (plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) { + graphic = point.graphic; + shapeArgs = point.shapeArgs; + if (graphic) { // update + stop(graphic); + graphic.animate(merge(shapeArgs)); + + } else { + point.graphic = graphic = renderer[point.shapeType](shapeArgs) + .attr(point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE]) + .add(series.group) + .shadow(options.shadow, null, options.stacking && !options.borderRadius); + } + + } + }); + }, + /** + * Draw the individual tracker elements. + * This method is inherited by scatter and pie charts too. + */ + drawTracker: function () { + var series = this, + chart = series.chart, + renderer = chart.renderer, + shapeArgs, + tracker, + trackerLabel = +new Date(), + options = series.options, + cursor = options.cursor, + css = cursor && { cursor: cursor }, + trackerGroup = series.drawTrackerGroup(), + rel, + plotY, + validPlotY; + + each(series.points, function (point) { + tracker = point.tracker; + shapeArgs = point.trackerArgs || point.shapeArgs; + plotY = point.plotY; + validPlotY = !series.isCartesian || (plotY !== UNDEFINED && !isNaN(plotY)); + delete shapeArgs.strokeWidth; + if (point.y !== null && validPlotY) { + if (tracker) {// update + tracker.attr(shapeArgs); + + } else { + point.tracker = + renderer[point.shapeType](shapeArgs) + .attr({ + isTracker: trackerLabel, + fill: TRACKER_FILL, + visibility: series.visible ? VISIBLE : HIDDEN + }) + .on(hasTouch ? 'touchstart' : 'mouseover', function (event) { + rel = event.relatedTarget || event.fromElement; + if (chart.hoverSeries !== series && attr(rel, 'isTracker') !== trackerLabel) { + series.onMouseOver(); + } + point.onMouseOver(); + + }) + .on('mouseout', function (event) { + if (!options.stickyTracking) { + rel = event.relatedTarget || event.toElement; + if (attr(rel, 'isTracker') !== trackerLabel) { + series.onMouseOut(); + } + } + }) + .css(css) + .add(point.group || trackerGroup); // pies have point group - see issue #118 + } + } + }); + }, + + + /** + * Animate the column heights one by one from zero + * @param {Boolean} init Whether to initialize the animation or run it + */ + animate: function (init) { + var series = this, + points = series.points, + options = series.options; + + if (!init) { // run the animation + /* + * Note: Ideally the animation should be initialized by calling + * series.group.hide(), and then calling series.group.show() + * after the animation was started. But this rendered the shadows + * invisible in IE8 standards mode. If the columns flicker on large + * datasets, this is the cause. + */ + + each(points, function (point) { + var graphic = point.graphic, + shapeArgs = point.shapeArgs, + yAxis = series.yAxis, + threshold = options.threshold; + + if (graphic) { + // start values + graphic.attr({ + height: 0, + y: defined(threshold) ? + yAxis.getThreshold(threshold) : + yAxis.translate(yAxis.getExtremes().min, 0, 1, 0, 1) + }); + + // animate + graphic.animate({ + height: shapeArgs.height, + y: shapeArgs.y + }, options.animation); + } + }); + + + // delete this function to allow it only once + series.animate = null; + } + + }, + /** + * Remove this series from the chart + */ + remove: function () { + var series = this, + chart = series.chart; + + // column and bar series affects other series of the same type + // as they are either stacked or grouped + if (chart.hasRendered) { + each(chart.series, function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + + Series.prototype.remove.apply(series, arguments); + } + }); + seriesTypes.column = ColumnSeries; + /** + * Set the default options for bar + */ + defaultPlotOptions.bar = merge(defaultPlotOptions.column, { + dataLabels: { + align: 'left', + x: 5, + y: null, + verticalAlign: 'middle' + } + }); + /** + * The Bar series class + */ + var BarSeries = extendClass(ColumnSeries, { + type: 'bar', + inverted: true + }); + seriesTypes.bar = BarSeries; + + /** + * Set the default options for scatter + */ + defaultPlotOptions.scatter = merge(defaultSeriesOptions, { + lineWidth: 0, + states: { + hover: { + lineWidth: 0 + } + }, + tooltip: { + headerFormat: '{series.name}
        ', + pointFormat: 'x: {point.x}
        y: {point.y}
        ' + } + }); + + /** + * The scatter series class + */ + var ScatterSeries = extendClass(Series, { + type: 'scatter', + sorted: false, + /** + * Extend the base Series' translate method by adding shape type and + * arguments for the point trackers + */ + translate: function () { + var series = this; + + Series.prototype.translate.apply(series); + + each(series.points, function (point) { + point.shapeType = 'circle'; + point.shapeArgs = { + x: point.plotX, + y: point.plotY, + r: series.chart.options.tooltip.snap + }; + }); + }, + + /** + * Add tracking event listener to the series group, so the point graphics + * themselves act as trackers + */ + drawTracker: function () { + var series = this, + cursor = series.options.cursor, + css = cursor && { cursor: cursor }, + points = series.points, + i = points.length, + graphic; + + // Set an expando property for the point index, used below + while (i--) { + graphic = points[i].graphic; + if (graphic) { // doesn't exist for null points + graphic.element._i = i; + } + } + + // Add the event listeners, we need to do this only once + if (!series._hasTracking) { + series.group + .attr({ + isTracker: true + }) + .on(hasTouch ? 'touchstart' : 'mouseover', function (e) { + series.onMouseOver(); + if (e.target._i !== UNDEFINED) { // undefined on graph in scatterchart + points[e.target._i].onMouseOver(); + } + }) + .on('mouseout', function () { + if (!series.options.stickyTracking) { + series.onMouseOut(); + } + }) + .css(css); + } else { + series._hasTracking = true; + } + + } + }); + seriesTypes.scatter = ScatterSeries; + + /** + * Set the default options for pie + */ + defaultPlotOptions.pie = merge(defaultSeriesOptions, { + borderColor: '#FFFFFF', + borderWidth: 1, + center: ['50%', '50%'], + colorByPoint: true, // always true for pies + dataLabels: { + // align: null, + // connectorWidth: 1, + // connectorColor: point.color, + // connectorPadding: 5, + distance: 30, + enabled: true, + formatter: function () { + return this.point.name; + }, + // softConnector: true, + y: 5 + }, + //innerSize: 0, + legendType: 'point', + marker: null, // point options are specified in the base options + size: '75%', + showInLegend: false, + slicedOffset: 10, + states: { + hover: { + brightness: 0.1, + shadow: false + } + } + }); + + /** + * Extended point object for pies + */ + var PiePoint = extendClass(Point, { + /** + * Initiate the pie slice + */ + init: function () { + + Point.prototype.init.apply(this, arguments); + + var point = this, + toggleSlice; + + //visible: options.visible !== false, + extend(point, { + visible: point.visible !== false, + name: pick(point.name, 'Slice') + }); + + // add event listener for select + toggleSlice = function () { + point.slice(); + }; + addEvent(point, 'select', toggleSlice); + addEvent(point, 'unselect', toggleSlice); + + return point; + }, + + /** + * Toggle the visibility of the pie slice + * @param {Boolean} vis Whether to show the slice or not. If undefined, the + * visibility is toggled + */ + setVisible: function (vis) { + var point = this, + chart = point.series.chart, + tracker = point.tracker, + dataLabel = point.dataLabel, + connector = point.connector, + shadowGroup = point.shadowGroup, + method; + + // if called without an argument, toggle visibility + point.visible = vis = vis === UNDEFINED ? !point.visible : vis; + + method = vis ? 'show' : 'hide'; + + point.group[method](); + if (tracker) { + tracker[method](); + } + if (dataLabel) { + dataLabel[method](); + } + if (connector) { + connector[method](); + } + if (shadowGroup) { + shadowGroup[method](); + } + if (point.legendItem) { + chart.legend.colorizeItem(point, vis); + } + }, + + /** + * Set or toggle whether the slice is cut out from the pie + * @param {Boolean} sliced When undefined, the slice state is toggled + * @param {Boolean} redraw Whether to redraw the chart. True by default. + */ + slice: function (sliced, redraw, animation) { + var point = this, + series = point.series, + chart = series.chart, + slicedTranslation = point.slicedTranslation, + translation; + + setAnimation(animation, chart); + + // redraw is true by default + redraw = pick(redraw, true); + + // if called without an argument, toggle + sliced = point.sliced = defined(sliced) ? sliced : !point.sliced; + + translation = { + translateX: (sliced ? slicedTranslation[0] : chart.plotLeft), + translateY: (sliced ? slicedTranslation[1] : chart.plotTop) + }; + point.group.animate(translation); + if (point.shadowGroup) { + point.shadowGroup.animate(translation); + } + + } + }); + + /** + * The Pie series class + */ + var PieSeries = { + type: 'pie', + isCartesian: false, + pointClass: PiePoint, + pointAttrToOptions: { // mapping between SVG attributes and the corresponding options + stroke: 'borderColor', + 'stroke-width': 'borderWidth', + fill: 'color' + }, + + /** + * Pies have one color each point + */ + getColor: function () { + // record first color for use in setData + this.initialColor = this.chart.counters.color; + }, + + /** + * Animate the pies in + */ + animate: function () { + var series = this, + points = series.points; + + each(points, function (point) { + var graphic = point.graphic, + args = point.shapeArgs, + up = -mathPI / 2; + + if (graphic) { + // start values + graphic.attr({ + r: 0, + start: up, + end: up + }); + + // animate + graphic.animate({ + r: args.r, + start: args.start, + end: args.end + }, series.options.animation); + } + }); + + // delete this function to allow it only once + series.animate = null; + + }, + + /** + * Extend the basic setData method by running processData and generatePoints immediately, + * in order to access the points from the legend. + */ + setData: function (data, redraw) { + Series.prototype.setData.call(this, data, false); + this.processData(); + this.generatePoints(); + if (pick(redraw, true)) { + this.chart.redraw(); + } + }, + + /** + * Get the center of the pie based on the size and center options relative to the + * plot area. Borrowed by the polar and gauge series types. + */ + getCenter: function () { + + var options = this.options, + chart = this.chart, + plotWidth = chart.plotWidth, + plotHeight = chart.plotHeight, + positions = options.center.concat([options.size, options.innerSize || 0]), + smallestSize = mathMin(plotWidth, plotHeight), + isPercent; + + return map(positions, function (length, i) { + + isPercent = /%$/.test(length); + return isPercent ? + // i == 0: centerX, relative to width + // i == 1: centerY, relative to height + // i == 2: size, relative to smallestSize + // i == 4: innerSize, relative to smallestSize + [plotWidth, plotHeight, smallestSize, smallestSize][i] * + pInt(length) / 100 : + length; + }); + }, + + /** + * Do translation for pie slices + */ + translate: function () { + this.generatePoints(); + + var total = 0, + series = this, + cumulative = -0.25, // start at top + precision = 1000, // issue #172 + options = series.options, + slicedOffset = options.slicedOffset, + connectorOffset = slicedOffset + options.borderWidth, + positions, + chart = series.chart, + start, + end, + angle, + points = series.points, + circ = 2 * mathPI, + fraction, + radiusX, // the x component of the radius vector for a given point + radiusY, + labelDistance = options.dataLabels.distance; + + // get positions - either an integer or a percentage string must be given + series.center = positions = series.getCenter(); + + // utility for getting the x value from a given y, used for anticollision logic in data labels + series.getX = function (y, left) { + + angle = math.asin((y - positions[1]) / (positions[2] / 2 + labelDistance)); + + return positions[0] + + (left ? -1 : 1) * + (mathCos(angle) * (positions[2] / 2 + labelDistance)); + }; + + // get the total sum + each(points, function (point) { + total += point.y; + }); + + each(points, function (point) { + // set start and end angle + fraction = total ? point.y / total : 0; + start = mathRound(cumulative * circ * precision) / precision; + cumulative += fraction; + end = mathRound(cumulative * circ * precision) / precision; + + // set the shape + point.shapeType = 'arc'; + point.shapeArgs = { + x: positions[0], + y: positions[1], + r: positions[2] / 2, + innerR: positions[3] / 2, + start: start, + end: end + }; + + // center for the sliced out slice + angle = (end + start) / 2; + point.slicedTranslation = map([ + mathCos(angle) * slicedOffset + chart.plotLeft, + mathSin(angle) * slicedOffset + chart.plotTop + ], mathRound); + + // set the anchor point for tooltips + radiusX = mathCos(angle) * positions[2] / 2; + radiusY = mathSin(angle) * positions[2] / 2; + point.tooltipPos = [ + positions[0] + radiusX * 0.7, + positions[1] + radiusY * 0.7 + ]; + + // set the anchor point for data labels + point.labelPos = [ + positions[0] + radiusX + mathCos(angle) * labelDistance, // first break of connector + positions[1] + radiusY + mathSin(angle) * labelDistance, // a/a + positions[0] + radiusX + mathCos(angle) * connectorOffset, // second break, right outside pie + positions[1] + radiusY + mathSin(angle) * connectorOffset, // a/a + positions[0] + radiusX, // landing point for connector + positions[1] + radiusY, // a/a + labelDistance < 0 ? // alignment + 'center' : + angle < circ / 4 ? 'left' : 'right', // alignment + angle // center angle + ]; + + // API properties + point.percentage = fraction * 100; + point.total = total; + + }); + + + this.setTooltipPoints(); + }, + + /** + * Render the slices + */ + render: function () { + var series = this; + + // cache attributes for shapes + series.getAttribs(); + + this.drawPoints(); + + // draw the mouse tracking area + if (series.options.enableMouseTracking !== false) { + series.drawTracker(); + } + + this.drawDataLabels(); + + if (series.options.animation && series.animate) { + series.animate(); + } + + // (See #322) series.isDirty = series.isDirtyData = false; // means data is in accordance with what you see + series.isDirty = false; // means data is in accordance with what you see + }, + + /** + * Draw the data points + */ + drawPoints: function () { + var series = this, + chart = series.chart, + renderer = chart.renderer, + groupTranslation, + //center, + graphic, + group, + shadow = series.options.shadow, + shadowGroup, + shapeArgs; + + // draw the slices + each(series.points, function (point) { + graphic = point.graphic; + shapeArgs = point.shapeArgs; + group = point.group; + shadowGroup = point.shadowGroup; + + // put the shadow behind all points + if (shadow && !shadowGroup) { + shadowGroup = point.shadowGroup = renderer.g('shadow') + .attr({ zIndex: 4 }) + .add(); + } + + // create the group the first time + if (!group) { + group = point.group = renderer.g('point') + .attr({ zIndex: 5 }) + .add(); + } + + // if the point is sliced, use special translation, else use plot area traslation + groupTranslation = point.sliced ? point.slicedTranslation : [chart.plotLeft, chart.plotTop]; + group.translate(groupTranslation[0], groupTranslation[1]); + if (shadowGroup) { + shadowGroup.translate(groupTranslation[0], groupTranslation[1]); + } + + // draw the slice + if (graphic) { + graphic.animate(shapeArgs); + } else { + point.graphic = graphic = renderer.arc(shapeArgs) + .setRadialReference(series.center) + .attr(extend( + point.pointAttr[NORMAL_STATE], + { 'stroke-linejoin': 'round' } + )) + .add(point.group) + .shadow(shadow, shadowGroup); + + } + + // detect point specific visibility + if (point.visible === false) { + point.setVisible(false); + } + + }); + + }, + + /** + * Override the base drawDataLabels method by pie specific functionality + */ + drawDataLabels: function () { + var series = this, + data = series.data, + point, + chart = series.chart, + options = series.options.dataLabels, + connectorPadding = pick(options.connectorPadding, 10), + connectorWidth = pick(options.connectorWidth, 1), + connector, + connectorPath, + softConnector = pick(options.softConnector, true), + distanceOption = options.distance, + seriesCenter = series.center, + radius = seriesCenter[2] / 2, + centerY = seriesCenter[1], + outside = distanceOption > 0, + dataLabel, + labelPos, + labelHeight, + halves = [// divide the points into right and left halves for anti collision + [], // right + [] // left + ], + x, + y, + visibility, + rankArr, + sort, + i = 2, + j; + + // get out if not enabled + if (!options.enabled) { + return; + } + + // run parent method + Series.prototype.drawDataLabels.apply(series); + + // arrange points for detection collision + each(data, function (point) { + if (point.dataLabel) { // it may have been cancelled in the base method (#407) + halves[ + point.labelPos[7] < mathPI / 2 ? 0 : 1 + ].push(point); + } + }); + halves[1].reverse(); + + // define the sorting algorithm + sort = function (a, b) { + return b.y - a.y; + }; + + // assume equal label heights + labelHeight = halves[0][0] && halves[0][0].dataLabel && (halves[0][0].dataLabel.getBBox().height || 21); // 21 is for #968 + + /* Loop over the points in each half, starting from the top and bottom + * of the pie to detect overlapping labels. + */ + while (i--) { + + var slots = [], + slotsLength, + usedSlots = [], + points = halves[i], + pos, + length = points.length, + slotIndex; + + // Only do anti-collision when we are outside the pie and have connectors (#856) + if (distanceOption > 0) { + + // build the slots + for (pos = centerY - radius - distanceOption; pos <= centerY + radius + distanceOption; pos += labelHeight) { + slots.push(pos); + // visualize the slot + /* + var slotX = series.getX(pos, i) + chart.plotLeft - (i ? 100 : 0), + slotY = pos + chart.plotTop; + if (!isNaN(slotX)) { + chart.renderer.rect(slotX, slotY - 7, 100, labelHeight) + .attr({ + 'stroke-width': 1, + stroke: 'silver' + }) + .add(); + chart.renderer.text('Slot '+ (slots.length - 1), slotX, slotY + 4) + .attr({ + fill: 'silver' + }).add(); + } + // */ + } + slotsLength = slots.length; + + // if there are more values than available slots, remove lowest values + if (length > slotsLength) { + // create an array for sorting and ranking the points within each quarter + rankArr = [].concat(points); + rankArr.sort(sort); + j = length; + while (j--) { + rankArr[j].rank = j; + } + j = length; + while (j--) { + if (points[j].rank >= slotsLength) { + points.splice(j, 1); + } + } + length = points.length; + } + + // The label goes to the nearest open slot, but not closer to the edge than + // the label's index. + for (j = 0; j < length; j++) { + + point = points[j]; + labelPos = point.labelPos; + + var closest = 9999, + distance, + slotI; + + // find the closest slot index + for (slotI = 0; slotI < slotsLength; slotI++) { + distance = mathAbs(slots[slotI] - labelPos[1]); + if (distance < closest) { + closest = distance; + slotIndex = slotI; + } + } + + // if that slot index is closer to the edges of the slots, move it + // to the closest appropriate slot + if (slotIndex < j && slots[j] !== null) { // cluster at the top + slotIndex = j; + } else if (slotsLength < length - j + slotIndex && slots[j] !== null) { // cluster at the bottom + slotIndex = slotsLength - length + j; + while (slots[slotIndex] === null) { // make sure it is not taken + slotIndex++; + } + } else { + // Slot is taken, find next free slot below. In the next run, the next slice will find the + // slot above these, because it is the closest one + while (slots[slotIndex] === null) { // make sure it is not taken + slotIndex++; + } + } + + usedSlots.push({ i: slotIndex, y: slots[slotIndex] }); + slots[slotIndex] = null; // mark as taken + } + // sort them in order to fill in from the top + usedSlots.sort(sort); + } + + // now the used slots are sorted, fill them up sequentially + for (j = 0; j < length; j++) { + + var slot, naturalY; + + point = points[j]; + labelPos = point.labelPos; + dataLabel = point.dataLabel; + visibility = point.visible === false ? HIDDEN : VISIBLE; + naturalY = labelPos[1]; + + if (distanceOption > 0) { + slot = usedSlots.pop(); + slotIndex = slot.i; + + // if the slot next to currrent slot is free, the y value is allowed + // to fall back to the natural position + y = slot.y; + if ((naturalY > y && slots[slotIndex + 1] !== null) || + (naturalY < y && slots[slotIndex - 1] !== null)) { + y = naturalY; + } + + } else { + y = naturalY; + } + + // get the x - use the natural x position for first and last slot, to prevent the top + // and botton slice connectors from touching each other on either side + x = options.justify ? + seriesCenter[0] + (i ? -1 : 1) * (radius + distanceOption) : + series.getX(slotIndex === 0 || slotIndex === slots.length - 1 ? naturalY : y, i); + + // move or place the data label + dataLabel + .attr({ + visibility: visibility, + align: labelPos[6] + })[dataLabel.moved ? 'animate' : 'attr']({ + x: x + options.x + + ({ left: connectorPadding, right: -connectorPadding }[labelPos[6]] || 0), + y: y + options.y + }); + dataLabel.moved = true; + + // draw the connector + if (outside && connectorWidth) { + connector = point.connector; + + connectorPath = softConnector ? [ + M, + x + (labelPos[6] === 'left' ? 5 : -5), y, // end of the string at the label + 'C', + x, y, // first break, next to the label + 2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5], + labelPos[2], labelPos[3], // second break + L, + labelPos[4], labelPos[5] // base + ] : [ + M, + x + (labelPos[6] === 'left' ? 5 : -5), y, // end of the string at the label + L, + labelPos[2], labelPos[3], // second break + L, + labelPos[4], labelPos[5] // base + ]; + + if (connector) { + connector.animate({ d: connectorPath }); + connector.attr('visibility', visibility); + + } else { + point.connector = connector = series.chart.renderer.path(connectorPath).attr({ + 'stroke-width': connectorWidth, + stroke: options.connectorColor || point.color || '#606060', + visibility: visibility, + zIndex: 3 + }) + .translate(chart.plotLeft, chart.plotTop) + .add(); + } + } + } + } + }, + + /** + * Draw point specific tracker objects. Inherit directly from column series. + */ + drawTracker: ColumnSeries.prototype.drawTracker, + + /** + * Use a simple symbol from column prototype + */ + drawLegendSymbol: AreaSeries.prototype.drawLegendSymbol, + + /** + * Pies don't have point marker symbols + */ + getSymbol: function () { + } + + }; + PieSeries = extendClass(Series, PieSeries); + seriesTypes.pie = PieSeries; + + +// global variables + extend(Highcharts, { + + // Constructors + Axis: Axis, + CanVGRenderer: CanVGRenderer, + Chart: Chart, + Color: Color, + Legend: Legend, + Point: Point, + Tick: Tick, + Tooltip: Tooltip, + Renderer: Renderer, + Series: Series, + SVGRenderer: SVGRenderer, + VMLRenderer: VMLRenderer, + + // Various + dateFormat: dateFormat, + pathAnim: pathAnim, + getOptions: getOptions, + hasBidiBug: hasBidiBug, + numberFormat: numberFormat, + seriesTypes: seriesTypes, + setOptions: setOptions, + addEvent: addEvent, + removeEvent: removeEvent, + createElement: createElement, + discardElement: discardElement, + css: css, + each: each, + extend: extend, + map: map, + merge: merge, + pick: pick, + splat: splat, + extendClass: extendClass, + pInt: pInt, + product: 'Highcharts', + version: '2.2.5' + }); +}()); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/canvas-tools.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/canvas-tools.js new file mode 100644 index 0000000..45ea867 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/canvas-tools.js @@ -0,0 +1,1590 @@ +/* + A class to parse color values + @author Stoyan Stefanov + @link http://www.phpied.com/rgb-color-parser-in-javascript/ + Use it if you like it + + canvg.js - Javascript SVG parser and renderer on Canvas + MIT Licensed + Gabe Lerner (gabelerner@gmail.com) + http://code.google.com/p/canvg/ + + Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/ + + Highcharts JS v2.2.5 (2012-06-08) + CanVGRenderer Extension module + + (c) 2011-2012 Torstein H?nsi, Erik Olsson + + License: www.highcharts.com/license + */ +function RGBColor(m) { + this.ok = !1; + m.charAt(0) == "#" && (m = m.substr(1, 6)); + var m = m.replace(/ /g, ""), m = m.toLowerCase(), a = {aliceblue: "f0f8ff", antiquewhite: "faebd7", aqua: "00ffff", aquamarine: "7fffd4", azure: "f0ffff", beige: "f5f5dc", bisque: "ffe4c4", black: "000000", blanchedalmond: "ffebcd", blue: "0000ff", blueviolet: "8a2be2", brown: "a52a2a", burlywood: "deb887", cadetblue: "5f9ea0", chartreuse: "7fff00", chocolate: "d2691e", coral: "ff7f50", cornflowerblue: "6495ed", cornsilk: "fff8dc", crimson: "dc143c", cyan: "00ffff", darkblue: "00008b", + darkcyan: "008b8b", darkgoldenrod: "b8860b", darkgray: "a9a9a9", darkgreen: "006400", darkkhaki: "bdb76b", darkmagenta: "8b008b", darkolivegreen: "556b2f", darkorange: "ff8c00", darkorchid: "9932cc", darkred: "8b0000", darksalmon: "e9967a", darkseagreen: "8fbc8f", darkslateblue: "483d8b", darkslategray: "2f4f4f", darkturquoise: "00ced1", darkviolet: "9400d3", deeppink: "ff1493", deepskyblue: "00bfff", dimgray: "696969", dodgerblue: "1e90ff", feldspar: "d19275", firebrick: "b22222", floralwhite: "fffaf0", forestgreen: "228b22", fuchsia: "ff00ff", + gainsboro: "dcdcdc", ghostwhite: "f8f8ff", gold: "ffd700", goldenrod: "daa520", gray: "808080", green: "008000", greenyellow: "adff2f", honeydew: "f0fff0", hotpink: "ff69b4", indianred: "cd5c5c", indigo: "4b0082", ivory: "fffff0", khaki: "f0e68c", lavender: "e6e6fa", lavenderblush: "fff0f5", lawngreen: "7cfc00", lemonchiffon: "fffacd", lightblue: "add8e6", lightcoral: "f08080", lightcyan: "e0ffff", lightgoldenrodyellow: "fafad2", lightgrey: "d3d3d3", lightgreen: "90ee90", lightpink: "ffb6c1", lightsalmon: "ffa07a", lightseagreen: "20b2aa", lightskyblue: "87cefa", + lightslateblue: "8470ff", lightslategray: "778899", lightsteelblue: "b0c4de", lightyellow: "ffffe0", lime: "00ff00", limegreen: "32cd32", linen: "faf0e6", magenta: "ff00ff", maroon: "800000", mediumaquamarine: "66cdaa", mediumblue: "0000cd", mediumorchid: "ba55d3", mediumpurple: "9370d8", mediumseagreen: "3cb371", mediumslateblue: "7b68ee", mediumspringgreen: "00fa9a", mediumturquoise: "48d1cc", mediumvioletred: "c71585", midnightblue: "191970", mintcream: "f5fffa", mistyrose: "ffe4e1", moccasin: "ffe4b5", navajowhite: "ffdead", navy: "000080", + oldlace: "fdf5e6", olive: "808000", olivedrab: "6b8e23", orange: "ffa500", orangered: "ff4500", orchid: "da70d6", palegoldenrod: "eee8aa", palegreen: "98fb98", paleturquoise: "afeeee", palevioletred: "d87093", papayawhip: "ffefd5", peachpuff: "ffdab9", peru: "cd853f", pink: "ffc0cb", plum: "dda0dd", powderblue: "b0e0e6", purple: "800080", red: "ff0000", rosybrown: "bc8f8f", royalblue: "4169e1", saddlebrown: "8b4513", salmon: "fa8072", sandybrown: "f4a460", seagreen: "2e8b57", seashell: "fff5ee", sienna: "a0522d", silver: "c0c0c0", skyblue: "87ceeb", slateblue: "6a5acd", + slategray: "708090", snow: "fffafa", springgreen: "00ff7f", steelblue: "4682b4", tan: "d2b48c", teal: "008080", thistle: "d8bfd8", tomato: "ff6347", turquoise: "40e0d0", violet: "ee82ee", violetred: "d02090", wheat: "f5deb3", white: "ffffff", whitesmoke: "f5f5f5", yellow: "ffff00", yellowgreen: "9acd32"}, c; + for (c in a)m == c && (m = a[c]); + var d = [ + {re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, example: ["rgb(123, 234, 45)", "rgb(255,234,245)"], process: function (b) { + return[parseInt(b[1]), parseInt(b[2]), parseInt(b[3])] + }}, + {re: /^(\w{2})(\w{2})(\w{2})$/, + example: ["#00ff00", "336699"], process: function (b) { + return[parseInt(b[1], 16), parseInt(b[2], 16), parseInt(b[3], 16)] + }}, + {re: /^(\w{1})(\w{1})(\w{1})$/, example: ["#fb0", "f0f"], process: function (b) { + return[parseInt(b[1] + b[1], 16), parseInt(b[2] + b[2], 16), parseInt(b[3] + b[3], 16)] + }} + ]; + for (c = 0; c < d.length; c++) { + var b = d[c].process, k = d[c].re.exec(m); + if (k)channels = b(k), this.r = channels[0], this.g = channels[1], this.b = channels[2], this.ok = !0 + } + this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r; + this.g = this.g < 0 || isNaN(this.g) ? 0 : + this.g > 255 ? 255 : this.g; + this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b; + this.toRGB = function () { + return"rgb(" + this.r + ", " + this.g + ", " + this.b + ")" + }; + this.toHex = function () { + var b = this.r.toString(16), a = this.g.toString(16), d = this.b.toString(16); + b.length == 1 && (b = "0" + b); + a.length == 1 && (a = "0" + a); + d.length == 1 && (d = "0" + d); + return"#" + b + a + d + }; + this.getHelpXML = function () { + for (var b = [], k = 0; k < d.length; k++)for (var c = d[k].example, j = 0; j < c.length; j++)b[b.length] = c[j]; + for (var h in a)b[b.length] = h; + c = document.createElement("ul"); + c.setAttribute("id", "rgbcolor-examples"); + for (k = 0; k < b.length; k++)try { + var l = document.createElement("li"), o = new RGBColor(b[k]), n = document.createElement("div"); + n.style.cssText = "margin: 3px; border: 1px solid black; background:" + o.toHex() + "; color:" + o.toHex(); + n.appendChild(document.createTextNode("test")); + var q = document.createTextNode(" " + b[k] + " -> " + o.toRGB() + " -> " + o.toHex()); + l.appendChild(n); + l.appendChild(q); + c.appendChild(l) + } catch (p) { + } + return c + } +} +if (!window.console)window.console = {}, window.console.log = function () { +}, window.console.dir = function () { +}; +if (!Array.prototype.indexOf)Array.prototype.indexOf = function (m) { + for (var a = 0; a < this.length; a++)if (this[a] == m)return a; + return-1 +}; +(function () { + function m() { + var a = {FRAMERATE: 30, MAX_VIRTUAL_PIXELS: 3E4}; + a.init = function (c) { + a.Definitions = {}; + a.Styles = {}; + a.Animations = []; + a.Images = []; + a.ctx = c; + a.ViewPort = new function () { + this.viewPorts = []; + this.Clear = function () { + this.viewPorts = [] + }; + this.SetCurrent = function (a, b) { + this.viewPorts.push({width: a, height: b}) + }; + this.RemoveCurrent = function () { + this.viewPorts.pop() + }; + this.Current = function () { + return this.viewPorts[this.viewPorts.length - 1] + }; + this.width = function () { + return this.Current().width + }; + this.height = function () { + return this.Current().height + }; + this.ComputeSize = function (a) { + return a != null && typeof a == "number" ? a : a == "x" ? this.width() : a == "y" ? this.height() : Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2) + } + } + }; + a.init(); + a.ImagesLoaded = function () { + for (var c = 0; c < a.Images.length; c++)if (!a.Images[c].loaded)return!1; + return!0 + }; + a.trim = function (a) { + return a.replace(/^\s+|\s+$/g, "") + }; + a.compressSpaces = function (a) { + return a.replace(/[\s\r\t\n]+/gm, " ") + }; + a.ajax = function (a) { + var d; + return(d = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP")) ? + (d.open("GET", a, !1), d.send(null), d.responseText) : null + }; + a.parseXml = function (a) { + if (window.DOMParser)return(new DOMParser).parseFromString(a, "text/xml"); else { + var a = a.replace(/]*>/, ""), d = new ActiveXObject("Microsoft.XMLDOM"); + d.async = "false"; + d.loadXML(a); + return d + } + }; + a.Property = function (c, d) { + this.name = c; + this.value = d; + this.hasValue = function () { + return this.value != null && this.value !== "" + }; + this.numValue = function () { + if (!this.hasValue())return 0; + var b = parseFloat(this.value); + (this.value + "").match(/%$/) && + (b /= 100); + return b + }; + this.valueOrDefault = function (b) { + return this.hasValue() ? this.value : b + }; + this.numValueOrDefault = function (b) { + return this.hasValue() ? this.numValue() : b + }; + var b = this; + this.Color = {addOpacity: function (d) { + var c = b.value; + if (d != null && d != "") { + var f = new RGBColor(b.value); + f.ok && (c = "rgba(" + f.r + ", " + f.g + ", " + f.b + ", " + d + ")") + } + return new a.Property(b.name, c) + }}; + this.Definition = {getDefinition: function () { + var d = b.value.replace(/^(url\()?#([^\)]+)\)?$/, "$2"); + return a.Definitions[d] + }, isUrl: function () { + return b.value.indexOf("url(") == + 0 + }, getFillStyle: function (b) { + var d = this.getDefinition(); + return d != null && d.createGradient ? d.createGradient(a.ctx, b) : d != null && d.createPattern ? d.createPattern(a.ctx, b) : null + }}; + this.Length = {DPI: function () { + return 96 + }, EM: function (b) { + var d = 12, c = new a.Property("fontSize", a.Font.Parse(a.ctx.font).fontSize); + c.hasValue() && (d = c.Length.toPixels(b)); + return d + }, toPixels: function (d) { + if (!b.hasValue())return 0; + var c = b.value + ""; + return c.match(/em$/) ? b.numValue() * this.EM(d) : c.match(/ex$/) ? b.numValue() * this.EM(d) / 2 : c.match(/px$/) ? + b.numValue() : c.match(/pt$/) ? b.numValue() * 1.25 : c.match(/pc$/) ? b.numValue() * 15 : c.match(/cm$/) ? b.numValue() * this.DPI(d) / 2.54 : c.match(/mm$/) ? b.numValue() * this.DPI(d) / 25.4 : c.match(/in$/) ? b.numValue() * this.DPI(d) : c.match(/%$/) ? b.numValue() * a.ViewPort.ComputeSize(d) : b.numValue() + }}; + this.Time = {toMilliseconds: function () { + if (!b.hasValue())return 0; + var a = b.value + ""; + if (a.match(/s$/))return b.numValue() * 1E3; + a.match(/ms$/); + return b.numValue() + }}; + this.Angle = {toRadians: function () { + if (!b.hasValue())return 0; + var a = b.value + + ""; + return a.match(/deg$/) ? b.numValue() * (Math.PI / 180) : a.match(/grad$/) ? b.numValue() * (Math.PI / 200) : a.match(/rad$/) ? b.numValue() : b.numValue() * (Math.PI / 180) + }} + }; + a.Font = new function () { + this.Styles = ["normal", "italic", "oblique", "inherit"]; + this.Variants = ["normal", "small-caps", "inherit"]; + this.Weights = "normal,bold,bolder,lighter,100,200,300,400,500,600,700,800,900,inherit".split(","); + this.CreateFont = function (d, b, c, e, f, g) { + g = g != null ? this.Parse(g) : this.CreateFont("", "", "", "", "", a.ctx.font); + return{fontFamily: f || + g.fontFamily, fontSize: e || g.fontSize, fontStyle: d || g.fontStyle, fontWeight: c || g.fontWeight, fontVariant: b || g.fontVariant, toString: function () { + return[this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(" ") + }} + }; + var c = this; + this.Parse = function (d) { + for (var b = {}, d = a.trim(a.compressSpaces(d || "")).split(" "), k = !1, e = !1, f = !1, g = !1, j = "", h = 0; h < d.length; h++)if (!e && c.Styles.indexOf(d[h]) != -1) { + if (d[h] != "inherit")b.fontStyle = d[h]; + e = !0 + } else if (!g && c.Variants.indexOf(d[h]) != -1) { + if (d[h] != "inherit")b.fontVariant = + d[h]; + e = g = !0 + } else if (!f && c.Weights.indexOf(d[h]) != -1) { + if (d[h] != "inherit")b.fontWeight = d[h]; + e = g = f = !0 + } else if (k)d[h] != "inherit" && (j += d[h]); else { + if (d[h] != "inherit")b.fontSize = d[h].split("/")[0]; + e = g = f = k = !0 + } + if (j != "")b.fontFamily = j; + return b + } + }; + a.ToNumberArray = function (c) { + for (var c = a.trim(a.compressSpaces((c || "").replace(/,/g, " "))).split(" "), d = 0; d < c.length; d++)c[d] = parseFloat(c[d]); + return c + }; + a.Point = function (a, d) { + this.x = a; + this.y = d; + this.angleTo = function (b) { + return Math.atan2(b.y - this.y, b.x - this.x) + }; + this.applyTransform = + function (b) { + var a = this.x * b[1] + this.y * b[3] + b[5]; + this.x = this.x * b[0] + this.y * b[2] + b[4]; + this.y = a + } + }; + a.CreatePoint = function (c) { + c = a.ToNumberArray(c); + return new a.Point(c[0], c[1]) + }; + a.CreatePath = function (c) { + for (var c = a.ToNumberArray(c), d = [], b = 0; b < c.length; b += 2)d.push(new a.Point(c[b], c[b + 1])); + return d + }; + a.BoundingBox = function (a, d, b, k) { + this.y2 = this.x2 = this.y1 = this.x1 = Number.NaN; + this.x = function () { + return this.x1 + }; + this.y = function () { + return this.y1 + }; + this.width = function () { + return this.x2 - this.x1 + }; + this.height = function () { + return this.y2 - + this.y1 + }; + this.addPoint = function (b, a) { + if (b != null) { + if (isNaN(this.x1) || isNaN(this.x2))this.x2 = this.x1 = b; + if (b < this.x1)this.x1 = b; + if (b > this.x2)this.x2 = b + } + if (a != null) { + if (isNaN(this.y1) || isNaN(this.y2))this.y2 = this.y1 = a; + if (a < this.y1)this.y1 = a; + if (a > this.y2)this.y2 = a + } + }; + this.addX = function (b) { + this.addPoint(b, null) + }; + this.addY = function (b) { + this.addPoint(null, b) + }; + this.addBoundingBox = function (b) { + this.addPoint(b.x1, b.y1); + this.addPoint(b.x2, b.y2) + }; + this.addQuadraticCurve = function (b, a, d, c, k, l) { + d = b + 2 / 3 * (d - b); + c = a + 2 / 3 * (c - + a); + this.addBezierCurve(b, a, d, d + 1 / 3 * (k - b), c, c + 1 / 3 * (l - a), k, l) + }; + this.addBezierCurve = function (b, a, d, c, k, l, o, n) { + var q = [b, a], p = [d, c], t = [k, l], m = [o, n]; + this.addPoint(q[0], q[1]); + this.addPoint(m[0], m[1]); + for (i = 0; i <= 1; i++)b = function (b) { + return Math.pow(1 - b, 3) * q[i] + 3 * Math.pow(1 - b, 2) * b * p[i] + 3 * (1 - b) * Math.pow(b, 2) * t[i] + Math.pow(b, 3) * m[i] + }, a = 6 * q[i] - 12 * p[i] + 6 * t[i], d = -3 * q[i] + 9 * p[i] - 9 * t[i] + 3 * m[i], c = 3 * p[i] - 3 * q[i], d == 0 ? a != 0 && (a = -c / a, 0 < a && a < 1 && (i == 0 && this.addX(b(a)), i == 1 && this.addY(b(a)))) : (c = Math.pow(a, 2) - 4 * c * d, c < 0 || (k = + (-a + Math.sqrt(c)) / (2 * d), 0 < k && k < 1 && (i == 0 && this.addX(b(k)), i == 1 && this.addY(b(k))), a = (-a - Math.sqrt(c)) / (2 * d), 0 < a && a < 1 && (i == 0 && this.addX(b(a)), i == 1 && this.addY(b(a))))) + }; + this.isPointInBox = function (b, a) { + return this.x1 <= b && b <= this.x2 && this.y1 <= a && a <= this.y2 + }; + this.addPoint(a, d); + this.addPoint(b, k) + }; + a.Transform = function (c) { + var d = this; + this.Type = {}; + this.Type.translate = function (b) { + this.p = a.CreatePoint(b); + this.apply = function (b) { + b.translate(this.p.x || 0, this.p.y || 0) + }; + this.applyToPoint = function (b) { + b.applyTransform([1, + 0, 0, 1, this.p.x || 0, this.p.y || 0]) + } + }; + this.Type.rotate = function (b) { + b = a.ToNumberArray(b); + this.angle = new a.Property("angle", b[0]); + this.cx = b[1] || 0; + this.cy = b[2] || 0; + this.apply = function (b) { + b.translate(this.cx, this.cy); + b.rotate(this.angle.Angle.toRadians()); + b.translate(-this.cx, -this.cy) + }; + this.applyToPoint = function (b) { + var a = this.angle.Angle.toRadians(); + b.applyTransform([1, 0, 0, 1, this.p.x || 0, this.p.y || 0]); + b.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]); + b.applyTransform([1, 0, 0, 1, -this.p.x || + 0, -this.p.y || 0]) + } + }; + this.Type.scale = function (b) { + this.p = a.CreatePoint(b); + this.apply = function (b) { + b.scale(this.p.x || 1, this.p.y || this.p.x || 1) + }; + this.applyToPoint = function (b) { + b.applyTransform([this.p.x || 0, 0, 0, this.p.y || 0, 0, 0]) + } + }; + this.Type.matrix = function (b) { + this.m = a.ToNumberArray(b); + this.apply = function (b) { + b.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]) + }; + this.applyToPoint = function (b) { + b.applyTransform(this.m) + } + }; + this.Type.SkewBase = function (b) { + this.base = d.Type.matrix; + this.base(b); + this.angle = + new a.Property("angle", b) + }; + this.Type.SkewBase.prototype = new this.Type.matrix; + this.Type.skewX = function (b) { + this.base = d.Type.SkewBase; + this.base(b); + this.m = [1, 0, Math.tan(this.angle.Angle.toRadians()), 1, 0, 0] + }; + this.Type.skewX.prototype = new this.Type.SkewBase; + this.Type.skewY = function (b) { + this.base = d.Type.SkewBase; + this.base(b); + this.m = [1, Math.tan(this.angle.Angle.toRadians()), 0, 1, 0, 0] + }; + this.Type.skewY.prototype = new this.Type.SkewBase; + this.transforms = []; + this.apply = function (b) { + for (var a = 0; a < this.transforms.length; a++)this.transforms[a].apply(b) + }; + this.applyToPoint = function (b) { + for (var a = 0; a < this.transforms.length; a++)this.transforms[a].applyToPoint(b) + }; + for (var c = a.trim(a.compressSpaces(c)).split(/\s(?=[a-z])/), b = 0; b < c.length; b++) { + var k = c[b].split("(")[0], e = c[b].split("(")[1].replace(")", ""); + this.transforms.push(new this.Type[k](e)) + } + }; + a.AspectRatio = function (c, d, b, k, e, f, g, j, h, l) { + var d = a.compressSpaces(d), d = d.replace(/^defer\s/, ""), o = d.split(" ")[0] || "xMidYMid", d = d.split(" ")[1] || "meet", n = b / k, q = e / f, p = Math.min(n, q), m = Math.max(n, q); + d == "meet" && (k *= + p, f *= p); + d == "slice" && (k *= m, f *= m); + h = new a.Property("refX", h); + l = new a.Property("refY", l); + h.hasValue() && l.hasValue() ? c.translate(-p * h.Length.toPixels("x"), -p * l.Length.toPixels("y")) : (o.match(/^xMid/) && (d == "meet" && p == q || d == "slice" && m == q) && c.translate(b / 2 - k / 2, 0), o.match(/YMid$/) && (d == "meet" && p == n || d == "slice" && m == n) && c.translate(0, e / 2 - f / 2), o.match(/^xMax/) && (d == "meet" && p == q || d == "slice" && m == q) && c.translate(b - k, 0), o.match(/YMax$/) && (d == "meet" && p == n || d == "slice" && m == n) && c.translate(0, e - f)); + o == "none" ? c.scale(n, + q) : d == "meet" ? c.scale(p, p) : d == "slice" && c.scale(m, m); + c.translate(g == null ? 0 : -g, j == null ? 0 : -j) + }; + a.Element = {}; + a.Element.ElementBase = function (c) { + this.attributes = {}; + this.styles = {}; + this.children = []; + this.attribute = function (b, d) { + var c = this.attributes[b]; + if (c != null)return c; + c = new a.Property(b, ""); + d == !0 && (this.attributes[b] = c); + return c + }; + this.style = function (b, d) { + var c = this.styles[b]; + if (c != null)return c; + c = this.attribute(b); + if (c != null && c.hasValue())return c; + c = this.parent; + if (c != null && (c = c.style(b), c != null && c.hasValue()))return c; + c = new a.Property(b, ""); + d == !0 && (this.styles[b] = c); + return c + }; + this.render = function (b) { + if (this.style("display").value != "none" && this.attribute("visibility").value != "hidden") { + b.save(); + this.setContext(b); + if (this.attribute("mask").hasValue()) { + var a = this.attribute("mask").Definition.getDefinition(); + a != null && a.apply(b, this) + } else this.style("filter").hasValue() ? (a = this.style("filter").Definition.getDefinition(), a != null && a.apply(b, this)) : this.renderChildren(b); + this.clearContext(b); + b.restore() + } + }; + this.setContext = + function () { + }; + this.clearContext = function () { + }; + this.renderChildren = function (b) { + for (var a = 0; a < this.children.length; a++)this.children[a].render(b) + }; + this.addChild = function (b, d) { + var c = b; + d && (c = a.CreateElement(b)); + c.parent = this; + this.children.push(c) + }; + if (c != null && c.nodeType == 1) { + for (var d = 0; d < c.childNodes.length; d++) { + var b = c.childNodes[d]; + b.nodeType == 1 && this.addChild(b, !0) + } + for (d = 0; d < c.attributes.length; d++)b = c.attributes[d], this.attributes[b.nodeName] = new a.Property(b.nodeName, b.nodeValue); + b = a.Styles[c.nodeName]; + if (b != null)for (var k in b)this.styles[k] = b[k]; + if (this.attribute("class").hasValue())for (var d = a.compressSpaces(this.attribute("class").value).split(" "), e = 0; e < d.length; e++) { + b = a.Styles["." + d[e]]; + if (b != null)for (k in b)this.styles[k] = b[k]; + b = a.Styles[c.nodeName + "." + d[e]]; + if (b != null)for (k in b)this.styles[k] = b[k] + } + if (this.attribute("style").hasValue()) { + b = this.attribute("style").value.split(";"); + for (d = 0; d < b.length; d++)a.trim(b[d]) != "" && (c = b[d].split(":"), k = a.trim(c[0]), c = a.trim(c[1]), this.styles[k] = new a.Property(k, + c)) + } + this.attribute("id").hasValue() && a.Definitions[this.attribute("id").value] == null && (a.Definitions[this.attribute("id").value] = this) + } + }; + a.Element.RenderedElementBase = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.setContext = function (d) { + if (this.style("fill").Definition.isUrl()) { + var b = this.style("fill").Definition.getFillStyle(this); + if (b != null)d.fillStyle = b + } else if (this.style("fill").hasValue())b = this.style("fill"), this.style("fill-opacity").hasValue() && (b = b.Color.addOpacity(this.style("fill-opacity").value)), + d.fillStyle = b.value == "none" ? "rgba(0,0,0,0)" : b.value; + if (this.style("stroke").Definition.isUrl()) { + if (b = this.style("stroke").Definition.getFillStyle(this), b != null)d.strokeStyle = b + } else if (this.style("stroke").hasValue())b = this.style("stroke"), this.style("stroke-opacity").hasValue() && (b = b.Color.addOpacity(this.style("stroke-opacity").value)), d.strokeStyle = b.value == "none" ? "rgba(0,0,0,0)" : b.value; + if (this.style("stroke-width").hasValue())d.lineWidth = this.style("stroke-width").Length.toPixels(); + if (this.style("stroke-linecap").hasValue())d.lineCap = + this.style("stroke-linecap").value; + if (this.style("stroke-linejoin").hasValue())d.lineJoin = this.style("stroke-linejoin").value; + if (this.style("stroke-miterlimit").hasValue())d.miterLimit = this.style("stroke-miterlimit").value; + if (typeof d.font != "undefined")d.font = a.Font.CreateFont(this.style("font-style").value, this.style("font-variant").value, this.style("font-weight").value, this.style("font-size").hasValue() ? this.style("font-size").Length.toPixels() + "px" : "", this.style("font-family").value).toString(); + this.attribute("transform").hasValue() && (new a.Transform(this.attribute("transform").value)).apply(d); + this.attribute("clip-path").hasValue() && (b = this.attribute("clip-path").Definition.getDefinition(), b != null && b.apply(d)); + if (this.style("opacity").hasValue())d.globalAlpha = this.style("opacity").numValue() + } + }; + a.Element.RenderedElementBase.prototype = new a.Element.ElementBase; + a.Element.PathElementBase = function (c) { + this.base = a.Element.RenderedElementBase; + this.base(c); + this.path = function (d) { + d != null && d.beginPath(); + return new a.BoundingBox + }; + this.renderChildren = function (d) { + this.path(d); + a.Mouse.checkPath(this, d); + d.fillStyle != "" && d.fill(); + d.strokeStyle != "" && d.stroke(); + var b = this.getMarkers(); + if (b != null) { + if (this.style("marker-start").Definition.isUrl()) { + var c = this.style("marker-start").Definition.getDefinition(); + c.render(d, b[0][0], b[0][1]) + } + if (this.style("marker-mid").Definition.isUrl())for (var c = this.style("marker-mid").Definition.getDefinition(), e = 1; e < b.length - 1; e++)c.render(d, b[e][0], b[e][1]); + this.style("marker-end").Definition.isUrl() && + (c = this.style("marker-end").Definition.getDefinition(), c.render(d, b[b.length - 1][0], b[b.length - 1][1])) + } + }; + this.getBoundingBox = function () { + return this.path() + }; + this.getMarkers = function () { + return null + } + }; + a.Element.PathElementBase.prototype = new a.Element.RenderedElementBase; + a.Element.svg = function (c) { + this.base = a.Element.RenderedElementBase; + this.base(c); + this.baseClearContext = this.clearContext; + this.clearContext = function (d) { + this.baseClearContext(d); + a.ViewPort.RemoveCurrent() + }; + this.baseSetContext = this.setContext; + this.setContext = function (d) { + d.strokeStyle = "rgba(0,0,0,0)"; + d.lineCap = "butt"; + d.lineJoin = "miter"; + d.miterLimit = 4; + this.baseSetContext(d); + this.attribute("x").hasValue() && this.attribute("y").hasValue() && d.translate(this.attribute("x").Length.toPixels("x"), this.attribute("y").Length.toPixels("y")); + var b = a.ViewPort.width(), c = a.ViewPort.height(); + if (typeof this.root == "undefined" && this.attribute("width").hasValue() && this.attribute("height").hasValue()) { + var b = this.attribute("width").Length.toPixels("x"), c = this.attribute("height").Length.toPixels("y"), + e = 0, f = 0; + this.attribute("refX").hasValue() && this.attribute("refY").hasValue() && (e = -this.attribute("refX").Length.toPixels("x"), f = -this.attribute("refY").Length.toPixels("y")); + d.beginPath(); + d.moveTo(e, f); + d.lineTo(b, f); + d.lineTo(b, c); + d.lineTo(e, c); + d.closePath(); + d.clip() + } + a.ViewPort.SetCurrent(b, c); + if (this.attribute("viewBox").hasValue()) { + var e = a.ToNumberArray(this.attribute("viewBox").value), f = e[0], g = e[1], b = e[2], c = e[3]; + a.AspectRatio(d, this.attribute("preserveAspectRatio").value, a.ViewPort.width(), b, a.ViewPort.height(), + c, f, g, this.attribute("refX").value, this.attribute("refY").value); + a.ViewPort.RemoveCurrent(); + a.ViewPort.SetCurrent(e[2], e[3]) + } + } + }; + a.Element.svg.prototype = new a.Element.RenderedElementBase; + a.Element.rect = function (c) { + this.base = a.Element.PathElementBase; + this.base(c); + this.path = function (d) { + var b = this.attribute("x").Length.toPixels("x"), c = this.attribute("y").Length.toPixels("y"), e = this.attribute("width").Length.toPixels("x"), f = this.attribute("height").Length.toPixels("y"), g = this.attribute("rx").Length.toPixels("x"), + j = this.attribute("ry").Length.toPixels("y"); + this.attribute("rx").hasValue() && !this.attribute("ry").hasValue() && (j = g); + this.attribute("ry").hasValue() && !this.attribute("rx").hasValue() && (g = j); + d != null && (d.beginPath(), d.moveTo(b + g, c), d.lineTo(b + e - g, c), d.quadraticCurveTo(b + e, c, b + e, c + j), d.lineTo(b + e, c + f - j), d.quadraticCurveTo(b + e, c + f, b + e - g, c + f), d.lineTo(b + g, c + f), d.quadraticCurveTo(b, c + f, b, c + f - j), d.lineTo(b, c + j), d.quadraticCurveTo(b, c, b + g, c), d.closePath()); + return new a.BoundingBox(b, c, b + e, c + f) + } + }; + a.Element.rect.prototype = + new a.Element.PathElementBase; + a.Element.circle = function (c) { + this.base = a.Element.PathElementBase; + this.base(c); + this.path = function (d) { + var b = this.attribute("cx").Length.toPixels("x"), c = this.attribute("cy").Length.toPixels("y"), e = this.attribute("r").Length.toPixels(); + d != null && (d.beginPath(), d.arc(b, c, e, 0, Math.PI * 2, !0), d.closePath()); + return new a.BoundingBox(b - e, c - e, b + e, c + e) + } + }; + a.Element.circle.prototype = new a.Element.PathElementBase; + a.Element.ellipse = function (c) { + this.base = a.Element.PathElementBase; + this.base(c); + this.path = function (d) { + var b = 4 * ((Math.sqrt(2) - 1) / 3), c = this.attribute("rx").Length.toPixels("x"), e = this.attribute("ry").Length.toPixels("y"), f = this.attribute("cx").Length.toPixels("x"), g = this.attribute("cy").Length.toPixels("y"); + d != null && (d.beginPath(), d.moveTo(f, g - e), d.bezierCurveTo(f + b * c, g - e, f + c, g - b * e, f + c, g), d.bezierCurveTo(f + c, g + b * e, f + b * c, g + e, f, g + e), d.bezierCurveTo(f - b * c, g + e, f - c, g + b * e, f - c, g), d.bezierCurveTo(f - c, g - b * e, f - b * c, g - e, f, g - e), d.closePath()); + return new a.BoundingBox(f - c, g - e, f + c, g + e) + } + }; + a.Element.ellipse.prototype = + new a.Element.PathElementBase; + a.Element.line = function (c) { + this.base = a.Element.PathElementBase; + this.base(c); + this.getPoints = function () { + return[new a.Point(this.attribute("x1").Length.toPixels("x"), this.attribute("y1").Length.toPixels("y")), new a.Point(this.attribute("x2").Length.toPixels("x"), this.attribute("y2").Length.toPixels("y"))] + }; + this.path = function (d) { + var b = this.getPoints(); + d != null && (d.beginPath(), d.moveTo(b[0].x, b[0].y), d.lineTo(b[1].x, b[1].y)); + return new a.BoundingBox(b[0].x, b[0].y, b[1].x, b[1].y) + }; + this.getMarkers = function () { + var a = this.getPoints(), b = a[0].angleTo(a[1]); + return[ + [a[0], b], + [a[1], b] + ] + } + }; + a.Element.line.prototype = new a.Element.PathElementBase; + a.Element.polyline = function (c) { + this.base = a.Element.PathElementBase; + this.base(c); + this.points = a.CreatePath(this.attribute("points").value); + this.path = function (d) { + var b = new a.BoundingBox(this.points[0].x, this.points[0].y); + d != null && (d.beginPath(), d.moveTo(this.points[0].x, this.points[0].y)); + for (var c = 1; c < this.points.length; c++)b.addPoint(this.points[c].x, + this.points[c].y), d != null && d.lineTo(this.points[c].x, this.points[c].y); + return b + }; + this.getMarkers = function () { + for (var a = [], b = 0; b < this.points.length - 1; b++)a.push([this.points[b], this.points[b].angleTo(this.points[b + 1])]); + a.push([this.points[this.points.length - 1], a[a.length - 1][1]]); + return a + } + }; + a.Element.polyline.prototype = new a.Element.PathElementBase; + a.Element.polygon = function (c) { + this.base = a.Element.polyline; + this.base(c); + this.basePath = this.path; + this.path = function (a) { + var b = this.basePath(a); + a != null && (a.lineTo(this.points[0].x, + this.points[0].y), a.closePath()); + return b + } + }; + a.Element.polygon.prototype = new a.Element.polyline; + a.Element.path = function (c) { + this.base = a.Element.PathElementBase; + this.base(c); + c = this.attribute("d").value; + c = c.replace(/,/gm, " "); + c = c.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2"); + c = c.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2"); + c = c.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm, "$1 $2"); + c = c.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2"); + c = c.replace(/([0-9])([+\-])/gm, + "$1 $2"); + c = c.replace(/(\.[0-9]*)(\.)/gm, "$1 $2"); + c = c.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm, "$1 $3 $4 "); + c = a.compressSpaces(c); + c = a.trim(c); + this.PathParser = new function (d) { + this.tokens = d.split(" "); + this.reset = function () { + this.i = -1; + this.previousCommand = this.command = ""; + this.start = new a.Point(0, 0); + this.control = new a.Point(0, 0); + this.current = new a.Point(0, 0); + this.points = []; + this.angles = [] + }; + this.isEnd = function () { + return this.i >= this.tokens.length - 1 + }; + this.isCommandOrEnd = function () { + return this.isEnd() ? + !0 : this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null + }; + this.isRelativeCommand = function () { + return this.command == this.command.toLowerCase() + }; + this.getToken = function () { + this.i += 1; + return this.tokens[this.i] + }; + this.getScalar = function () { + return parseFloat(this.getToken()) + }; + this.nextCommand = function () { + this.previousCommand = this.command; + this.command = this.getToken() + }; + this.getPoint = function () { + return this.makeAbsolute(new a.Point(this.getScalar(), this.getScalar())) + }; + this.getAsControlPoint = function () { + var b = this.getPoint(); + return this.control = b + }; + this.getAsCurrentPoint = function () { + var b = this.getPoint(); + return this.current = b + }; + this.getReflectedControlPoint = function () { + return this.previousCommand.toLowerCase() != "c" && this.previousCommand.toLowerCase() != "s" ? this.current : new a.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y) + }; + this.makeAbsolute = function (b) { + if (this.isRelativeCommand())b.x = this.current.x + b.x, b.y = this.current.y + b.y; + return b + }; + this.addMarker = function (b, a, d) { + d != null && this.angles.length > 0 && this.angles[this.angles.length - + 1] == null && (this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(d)); + this.addMarkerAngle(b, a == null ? null : a.angleTo(b)) + }; + this.addMarkerAngle = function (b, a) { + this.points.push(b); + this.angles.push(a) + }; + this.getMarkerPoints = function () { + return this.points + }; + this.getMarkerAngles = function () { + for (var b = 0; b < this.angles.length; b++)if (this.angles[b] == null)for (var a = b + 1; a < this.angles.length; a++)if (this.angles[a] != null) { + this.angles[b] = this.angles[a]; + break + } + return this.angles + } + }(c); + this.path = function (d) { + var b = + this.PathParser; + b.reset(); + var c = new a.BoundingBox; + for (d != null && d.beginPath(); !b.isEnd();)switch (b.nextCommand(), b.command.toUpperCase()) { + case "M": + var e = b.getAsCurrentPoint(); + b.addMarker(e); + c.addPoint(e.x, e.y); + d != null && d.moveTo(e.x, e.y); + for (b.start = b.current; !b.isCommandOrEnd();)e = b.getAsCurrentPoint(), b.addMarker(e, b.start), c.addPoint(e.x, e.y), d != null && d.lineTo(e.x, e.y); + break; + case "L": + for (; !b.isCommandOrEnd();) { + var f = b.current, e = b.getAsCurrentPoint(); + b.addMarker(e, f); + c.addPoint(e.x, e.y); + d != null && + d.lineTo(e.x, e.y) + } + break; + case "H": + for (; !b.isCommandOrEnd();)e = new a.Point((b.isRelativeCommand() ? b.current.x : 0) + b.getScalar(), b.current.y), b.addMarker(e, b.current), b.current = e, c.addPoint(b.current.x, b.current.y), d != null && d.lineTo(b.current.x, b.current.y); + break; + case "V": + for (; !b.isCommandOrEnd();)e = new a.Point(b.current.x, (b.isRelativeCommand() ? b.current.y : 0) + b.getScalar()), b.addMarker(e, b.current), b.current = e, c.addPoint(b.current.x, b.current.y), d != null && d.lineTo(b.current.x, b.current.y); + break; + case "C": + for (; !b.isCommandOrEnd();) { + var g = + b.current, f = b.getPoint(), j = b.getAsControlPoint(), e = b.getAsCurrentPoint(); + b.addMarker(e, j, f); + c.addBezierCurve(g.x, g.y, f.x, f.y, j.x, j.y, e.x, e.y); + d != null && d.bezierCurveTo(f.x, f.y, j.x, j.y, e.x, e.y) + } + break; + case "S": + for (; !b.isCommandOrEnd();)g = b.current, f = b.getReflectedControlPoint(), j = b.getAsControlPoint(), e = b.getAsCurrentPoint(), b.addMarker(e, j, f), c.addBezierCurve(g.x, g.y, f.x, f.y, j.x, j.y, e.x, e.y), d != null && d.bezierCurveTo(f.x, f.y, j.x, j.y, e.x, e.y); + break; + case "Q": + for (; !b.isCommandOrEnd();)g = b.current, j = b.getAsControlPoint(), + e = b.getAsCurrentPoint(), b.addMarker(e, j, j), c.addQuadraticCurve(g.x, g.y, j.x, j.y, e.x, e.y), d != null && d.quadraticCurveTo(j.x, j.y, e.x, e.y); + break; + case "T": + for (; !b.isCommandOrEnd();)g = b.current, j = b.getReflectedControlPoint(), b.control = j, e = b.getAsCurrentPoint(), b.addMarker(e, j, j), c.addQuadraticCurve(g.x, g.y, j.x, j.y, e.x, e.y), d != null && d.quadraticCurveTo(j.x, j.y, e.x, e.y); + break; + case "A": + for (; !b.isCommandOrEnd();) { + var g = b.current, h = b.getScalar(), l = b.getScalar(), f = b.getScalar() * (Math.PI / 180), o = b.getScalar(), j = b.getScalar(), + e = b.getAsCurrentPoint(), n = new a.Point(Math.cos(f) * (g.x - e.x) / 2 + Math.sin(f) * (g.y - e.y) / 2, -Math.sin(f) * (g.x - e.x) / 2 + Math.cos(f) * (g.y - e.y) / 2), q = Math.pow(n.x, 2) / Math.pow(h, 2) + Math.pow(n.y, 2) / Math.pow(l, 2); + q > 1 && (h *= Math.sqrt(q), l *= Math.sqrt(q)); + o = (o == j ? -1 : 1) * Math.sqrt((Math.pow(h, 2) * Math.pow(l, 2) - Math.pow(h, 2) * Math.pow(n.y, 2) - Math.pow(l, 2) * Math.pow(n.x, 2)) / (Math.pow(h, 2) * Math.pow(n.y, 2) + Math.pow(l, 2) * Math.pow(n.x, 2))); + isNaN(o) && (o = 0); + var p = new a.Point(o * h * n.y / l, o * -l * n.x / h), g = new a.Point((g.x + e.x) / 2 + Math.cos(f) * + p.x - Math.sin(f) * p.y, (g.y + e.y) / 2 + Math.sin(f) * p.x + Math.cos(f) * p.y), m = function (b, a) { + return(b[0] * a[0] + b[1] * a[1]) / (Math.sqrt(Math.pow(b[0], 2) + Math.pow(b[1], 2)) * Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2))) + }, s = function (b, a) { + return(b[0] * a[1] < b[1] * a[0] ? -1 : 1) * Math.acos(m(b, a)) + }, o = s([1, 0], [(n.x - p.x) / h, (n.y - p.y) / l]), q = [(n.x - p.x) / h, (n.y - p.y) / l], p = [(-n.x - p.x) / h, (-n.y - p.y) / l], n = s(q, p); + if (m(q, p) <= -1)n = Math.PI; + m(q, p) >= 1 && (n = 0); + j == 0 && n > 0 && (n -= 2 * Math.PI); + j == 1 && n < 0 && (n += 2 * Math.PI); + q = new a.Point(g.x - h * Math.cos((o + n) / + 2), g.y - l * Math.sin((o + n) / 2)); + b.addMarkerAngle(q, (o + n) / 2 + (j == 0 ? 1 : -1) * Math.PI / 2); + b.addMarkerAngle(e, n + (j == 0 ? 1 : -1) * Math.PI / 2); + c.addPoint(e.x, e.y); + d != null && (m = h > l ? h : l, e = h > l ? 1 : h / l, h = h > l ? l / h : 1, d.translate(g.x, g.y), d.rotate(f), d.scale(e, h), d.arc(0, 0, m, o, o + n, 1 - j), d.scale(1 / e, 1 / h), d.rotate(-f), d.translate(-g.x, -g.y)) + } + break; + case "Z": + d != null && d.closePath(), b.current = b.start + } + return c + }; + this.getMarkers = function () { + for (var a = this.PathParser.getMarkerPoints(), b = this.PathParser.getMarkerAngles(), c = [], e = 0; e < a.length; e++)c.push([a[e], + b[e]]); + return c + } + }; + a.Element.path.prototype = new a.Element.PathElementBase; + a.Element.pattern = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.createPattern = function (d) { + var b = new a.Element.svg; + b.attributes.viewBox = new a.Property("viewBox", this.attribute("viewBox").value); + b.attributes.x = new a.Property("x", this.attribute("x").value); + b.attributes.y = new a.Property("y", this.attribute("y").value); + b.attributes.width = new a.Property("width", this.attribute("width").value); + b.attributes.height = new a.Property("height", + this.attribute("height").value); + b.children = this.children; + var c = document.createElement("canvas"); + c.width = this.attribute("width").Length.toPixels("x"); + c.height = this.attribute("height").Length.toPixels("y"); + b.render(c.getContext("2d")); + return d.createPattern(c, "repeat") + } + }; + a.Element.pattern.prototype = new a.Element.ElementBase; + a.Element.marker = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.baseRender = this.render; + this.render = function (d, b, c) { + d.translate(b.x, b.y); + this.attribute("orient").valueOrDefault("auto") == + "auto" && d.rotate(c); + this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth" && d.scale(d.lineWidth, d.lineWidth); + d.save(); + var e = new a.Element.svg; + e.attributes.viewBox = new a.Property("viewBox", this.attribute("viewBox").value); + e.attributes.refX = new a.Property("refX", this.attribute("refX").value); + e.attributes.refY = new a.Property("refY", this.attribute("refY").value); + e.attributes.width = new a.Property("width", this.attribute("markerWidth").value); + e.attributes.height = new a.Property("height", + this.attribute("markerHeight").value); + e.attributes.fill = new a.Property("fill", this.attribute("fill").valueOrDefault("black")); + e.attributes.stroke = new a.Property("stroke", this.attribute("stroke").valueOrDefault("none")); + e.children = this.children; + e.render(d); + d.restore(); + this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth" && d.scale(1 / d.lineWidth, 1 / d.lineWidth); + this.attribute("orient").valueOrDefault("auto") == "auto" && d.rotate(-c); + d.translate(-b.x, -b.y) + } + }; + a.Element.marker.prototype = + new a.Element.ElementBase; + a.Element.defs = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.render = function () { + } + }; + a.Element.defs.prototype = new a.Element.ElementBase; + a.Element.GradientBase = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.gradientUnits = this.attribute("gradientUnits").valueOrDefault("objectBoundingBox"); + this.stops = []; + for (c = 0; c < this.children.length; c++)this.stops.push(this.children[c]); + this.getGradient = function () { + }; + this.createGradient = function (d, b) { + var c = this; + this.attribute("xlink:href").hasValue() && + (c = this.attribute("xlink:href").Definition.getDefinition()); + for (var e = this.getGradient(d, b), f = 0; f < c.stops.length; f++)e.addColorStop(c.stops[f].offset, c.stops[f].color); + if (this.attribute("gradientTransform").hasValue()) { + c = a.ViewPort.viewPorts[0]; + f = new a.Element.rect; + f.attributes.x = new a.Property("x", -a.MAX_VIRTUAL_PIXELS / 3); + f.attributes.y = new a.Property("y", -a.MAX_VIRTUAL_PIXELS / 3); + f.attributes.width = new a.Property("width", a.MAX_VIRTUAL_PIXELS); + f.attributes.height = new a.Property("height", a.MAX_VIRTUAL_PIXELS); + var g = new a.Element.g; + g.attributes.transform = new a.Property("transform", this.attribute("gradientTransform").value); + g.children = [f]; + f = new a.Element.svg; + f.attributes.x = new a.Property("x", 0); + f.attributes.y = new a.Property("y", 0); + f.attributes.width = new a.Property("width", c.width); + f.attributes.height = new a.Property("height", c.height); + f.children = [g]; + g = document.createElement("canvas"); + g.width = c.width; + g.height = c.height; + c = g.getContext("2d"); + c.fillStyle = e; + f.render(c); + return c.createPattern(g, "no-repeat") + } + return e + } + }; + a.Element.GradientBase.prototype = new a.Element.ElementBase; + a.Element.linearGradient = function (c) { + this.base = a.Element.GradientBase; + this.base(c); + this.getGradient = function (a, b) { + var c = b.getBoundingBox(), e = this.gradientUnits == "objectBoundingBox" ? c.x() + c.width() * this.attribute("x1").numValue() : this.attribute("x1").Length.toPixels("x"), f = this.gradientUnits == "objectBoundingBox" ? c.y() + c.height() * this.attribute("y1").numValue() : this.attribute("y1").Length.toPixels("y"), g = this.gradientUnits == "objectBoundingBox" ? + c.x() + c.width() * this.attribute("x2").numValue() : this.attribute("x2").Length.toPixels("x"), c = this.gradientUnits == "objectBoundingBox" ? c.y() + c.height() * this.attribute("y2").numValue() : this.attribute("y2").Length.toPixels("y"); + return a.createLinearGradient(e, f, g, c) + } + }; + a.Element.linearGradient.prototype = new a.Element.GradientBase; + a.Element.radialGradient = function (c) { + this.base = a.Element.GradientBase; + this.base(c); + this.getGradient = function (a, b) { + var c = b.getBoundingBox(), e = this.gradientUnits == "objectBoundingBox" ? + c.x() + c.width() * this.attribute("cx").numValue() : this.attribute("cx").Length.toPixels("x"), f = this.gradientUnits == "objectBoundingBox" ? c.y() + c.height() * this.attribute("cy").numValue() : this.attribute("cy").Length.toPixels("y"), g = e, j = f; + this.attribute("fx").hasValue() && (g = this.gradientUnits == "objectBoundingBox" ? c.x() + c.width() * this.attribute("fx").numValue() : this.attribute("fx").Length.toPixels("x")); + this.attribute("fy").hasValue() && (j = this.gradientUnits == "objectBoundingBox" ? c.y() + c.height() * this.attribute("fy").numValue() : + this.attribute("fy").Length.toPixels("y")); + c = this.gradientUnits == "objectBoundingBox" ? (c.width() + c.height()) / 2 * this.attribute("r").numValue() : this.attribute("r").Length.toPixels(); + return a.createRadialGradient(g, j, 0, e, f, c) + } + }; + a.Element.radialGradient.prototype = new a.Element.GradientBase; + a.Element.stop = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.offset = this.attribute("offset").numValue(); + c = this.style("stop-color"); + this.style("stop-opacity").hasValue() && (c = c.Color.addOpacity(this.style("stop-opacity").value)); + this.color = c.value + }; + a.Element.stop.prototype = new a.Element.ElementBase; + a.Element.AnimateBase = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + a.Animations.push(this); + this.duration = 0; + this.begin = this.attribute("begin").Time.toMilliseconds(); + this.maxDuration = this.begin + this.attribute("dur").Time.toMilliseconds(); + this.getProperty = function () { + var a = this.attribute("attributeType").value, b = this.attribute("attributeName").value; + return a == "CSS" ? this.parent.style(b, !0) : this.parent.attribute(b, !0) + }; + this.initialValue = + null; + this.removed = !1; + this.calcValue = function () { + return"" + }; + this.update = function (a) { + if (this.initialValue == null)this.initialValue = this.getProperty().value; + if (this.duration > this.maxDuration)if (this.attribute("repeatCount").value == "indefinite")this.duration = 0; else return this.attribute("fill").valueOrDefault("remove") == "remove" && !this.removed ? (this.removed = !0, this.getProperty().value = this.initialValue, !0) : !1; + this.duration += a; + a = !1; + if (this.begin < this.duration)a = this.calcValue(), this.attribute("type").hasValue() && + (a = this.attribute("type").value + "(" + a + ")"), this.getProperty().value = a, a = !0; + return a + }; + this.progress = function () { + return(this.duration - this.begin) / (this.maxDuration - this.begin) + } + }; + a.Element.AnimateBase.prototype = new a.Element.ElementBase; + a.Element.animate = function (c) { + this.base = a.Element.AnimateBase; + this.base(c); + this.calcValue = function () { + var a = this.attribute("from").numValue(), b = this.attribute("to").numValue(); + return a + (b - a) * this.progress() + } + }; + a.Element.animate.prototype = new a.Element.AnimateBase; + a.Element.animateColor = + function (c) { + this.base = a.Element.AnimateBase; + this.base(c); + this.calcValue = function () { + var a = new RGBColor(this.attribute("from").value), b = new RGBColor(this.attribute("to").value); + if (a.ok && b.ok) { + var c = a.r + (b.r - a.r) * this.progress(), e = a.g + (b.g - a.g) * this.progress(), a = a.b + (b.b - a.b) * this.progress(); + return"rgb(" + parseInt(c, 10) + "," + parseInt(e, 10) + "," + parseInt(a, 10) + ")" + } + return this.attribute("from").value + } + }; + a.Element.animateColor.prototype = new a.Element.AnimateBase; + a.Element.animateTransform = function (c) { + this.base = + a.Element.animate; + this.base(c) + }; + a.Element.animateTransform.prototype = new a.Element.animate; + a.Element.font = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.horizAdvX = this.attribute("horiz-adv-x").numValue(); + this.isArabic = this.isRTL = !1; + this.missingGlyph = this.fontFace = null; + this.glyphs = []; + for (c = 0; c < this.children.length; c++) { + var d = this.children[c]; + if (d.type == "font-face")this.fontFace = d, d.style("font-family").hasValue() && (a.Definitions[d.style("font-family").value] = this); else if (d.type == "missing-glyph")this.missingGlyph = + d; else if (d.type == "glyph")d.arabicForm != "" ? (this.isArabic = this.isRTL = !0, typeof this.glyphs[d.unicode] == "undefined" && (this.glyphs[d.unicode] = []), this.glyphs[d.unicode][d.arabicForm] = d) : this.glyphs[d.unicode] = d + } + }; + a.Element.font.prototype = new a.Element.ElementBase; + a.Element.fontface = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.ascent = this.attribute("ascent").value; + this.descent = this.attribute("descent").value; + this.unitsPerEm = this.attribute("units-per-em").numValue() + }; + a.Element.fontface.prototype = + new a.Element.ElementBase; + a.Element.missingglyph = function (c) { + this.base = a.Element.path; + this.base(c); + this.horizAdvX = 0 + }; + a.Element.missingglyph.prototype = new a.Element.path; + a.Element.glyph = function (c) { + this.base = a.Element.path; + this.base(c); + this.horizAdvX = this.attribute("horiz-adv-x").numValue(); + this.unicode = this.attribute("unicode").value; + this.arabicForm = this.attribute("arabic-form").value + }; + a.Element.glyph.prototype = new a.Element.path; + a.Element.text = function (c) { + this.base = a.Element.RenderedElementBase; + this.base(c); + if (c != null) { + this.children = []; + for (var d = 0; d < c.childNodes.length; d++) { + var b = c.childNodes[d]; + b.nodeType == 1 ? this.addChild(b, !0) : b.nodeType == 3 && this.addChild(new a.Element.tspan(b), !1) + } + } + this.baseSetContext = this.setContext; + this.setContext = function (b) { + this.baseSetContext(b); + if (this.style("dominant-baseline").hasValue())b.textBaseline = this.style("dominant-baseline").value; + if (this.style("alignment-baseline").hasValue())b.textBaseline = this.style("alignment-baseline").value + }; + this.renderChildren = + function (b) { + for (var a = this.style("text-anchor").valueOrDefault("start"), c = this.attribute("x").Length.toPixels("x"), d = this.attribute("y").Length.toPixels("y"), j = 0; j < this.children.length; j++) { + var h = this.children[j]; + h.attribute("x").hasValue() ? h.x = h.attribute("x").Length.toPixels("x") : (h.attribute("dx").hasValue() && (c += h.attribute("dx").Length.toPixels("x")), h.x = c); + c = h.measureText(b); + if (a != "start" && (j == 0 || h.attribute("x").hasValue())) { + for (var l = c, o = j + 1; o < this.children.length; o++) { + var n = this.children[o]; + if (n.attribute("x").hasValue())break; + l += n.measureText(b) + } + h.x -= a == "end" ? l : l / 2 + } + c = h.x + c; + h.attribute("y").hasValue() ? h.y = h.attribute("y").Length.toPixels("y") : (h.attribute("dy").hasValue() && (d += h.attribute("dy").Length.toPixels("y")), h.y = d); + d = h.y; + h.render(b) + } + } + }; + a.Element.text.prototype = new a.Element.RenderedElementBase; + a.Element.TextElementBase = function (c) { + this.base = a.Element.RenderedElementBase; + this.base(c); + this.getGlyph = function (a, b, c) { + var e = b[c], f = null; + if (a.isArabic) { + var g = "isolated"; + if ((c == 0 || b[c - + 1] == " ") && c < b.length - 2 && b[c + 1] != " ")g = "terminal"; + c > 0 && b[c - 1] != " " && c < b.length - 2 && b[c + 1] != " " && (g = "medial"); + if (c > 0 && b[c - 1] != " " && (c == b.length - 1 || b[c + 1] == " "))g = "initial"; + typeof a.glyphs[e] != "undefined" && (f = a.glyphs[e][g], f == null && a.glyphs[e].type == "glyph" && (f = a.glyphs[e])) + } else f = a.glyphs[e]; + if (f == null)f = a.missingGlyph; + return f + }; + this.renderChildren = function (c) { + var b = this.parent.style("font-family").Definition.getDefinition(); + if (b != null) { + var k = this.parent.style("font-size").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize), + e = this.parent.style("font-style").valueOrDefault(a.Font.Parse(a.ctx.font).fontStyle), f = this.getText(); + b.isRTL && (f = f.split("").reverse().join("")); + for (var g = a.ToNumberArray(this.parent.attribute("dx").value), j = 0; j < f.length; j++) { + var h = this.getGlyph(b, f, j), l = k / b.fontFace.unitsPerEm; + c.translate(this.x, this.y); + c.scale(l, -l); + var o = c.lineWidth; + c.lineWidth = c.lineWidth * b.fontFace.unitsPerEm / k; + e == "italic" && c.transform(1, 0, 0.4, 1, 0, 0); + h.render(c); + e == "italic" && c.transform(1, 0, -0.4, 1, 0, 0); + c.lineWidth = o; + c.scale(1 / + l, -1 / l); + c.translate(-this.x, -this.y); + this.x += k * (h.horizAdvX || b.horizAdvX) / b.fontFace.unitsPerEm; + typeof g[j] != "undefined" && !isNaN(g[j]) && (this.x += g[j]) + } + } else c.strokeStyle != "" && c.strokeText(a.compressSpaces(this.getText()), this.x, this.y), c.fillStyle != "" && c.fillText(a.compressSpaces(this.getText()), this.x, this.y) + }; + this.getText = function () { + }; + this.measureText = function (c) { + var b = this.parent.style("font-family").Definition.getDefinition(); + if (b != null) { + var c = this.parent.style("font-size").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize), + k = 0, e = this.getText(); + b.isRTL && (e = e.split("").reverse().join("")); + for (var f = a.ToNumberArray(this.parent.attribute("dx").value), g = 0; g < e.length; g++) { + var j = this.getGlyph(b, e, g); + k += (j.horizAdvX || b.horizAdvX) * c / b.fontFace.unitsPerEm; + typeof f[g] != "undefined" && !isNaN(f[g]) && (k += f[g]) + } + return k + } + b = a.compressSpaces(this.getText()); + if (!c.measureText)return b.length * 10; + c.save(); + this.setContext(c); + b = c.measureText(b).width; + c.restore(); + return b + } + }; + a.Element.TextElementBase.prototype = new a.Element.RenderedElementBase; + a.Element.tspan = function (c) { + this.base = a.Element.TextElementBase; + this.base(c); + this.text = c.nodeType == 3 ? c.nodeValue : c.childNodes.length > 0 ? c.childNodes[0].nodeValue : c.text; + this.getText = function () { + return this.text + } + }; + a.Element.tspan.prototype = new a.Element.TextElementBase; + a.Element.tref = function (c) { + this.base = a.Element.TextElementBase; + this.base(c); + this.getText = function () { + var a = this.attribute("xlink:href").Definition.getDefinition(); + if (a != null)return a.children[0].getText() + } + }; + a.Element.tref.prototype = new a.Element.TextElementBase; + a.Element.a = function (c) { + this.base = a.Element.TextElementBase; + this.base(c); + this.hasText = !0; + for (var d = 0; d < c.childNodes.length; d++)if (c.childNodes[d].nodeType != 3)this.hasText = !1; + this.text = this.hasText ? c.childNodes[0].nodeValue : ""; + this.getText = function () { + return this.text + }; + this.baseRenderChildren = this.renderChildren; + this.renderChildren = function (b) { + if (this.hasText) { + this.baseRenderChildren(b); + var c = new a.Property("fontSize", a.Font.Parse(a.ctx.font).fontSize); + a.Mouse.checkBoundingBox(this, new a.BoundingBox(this.x, + this.y - c.Length.toPixels("y"), this.x + this.measureText(b), this.y)) + } else c = new a.Element.g, c.children = this.children, c.parent = this, c.render(b) + }; + this.onclick = function () { + window.open(this.attribute("xlink:href").value) + }; + this.onmousemove = function () { + a.ctx.canvas.style.cursor = "pointer" + } + }; + a.Element.a.prototype = new a.Element.TextElementBase; + a.Element.image = function (c) { + this.base = a.Element.RenderedElementBase; + this.base(c); + a.Images.push(this); + this.img = document.createElement("img"); + this.loaded = !1; + var d = this; + this.img.onload = + function () { + d.loaded = !0 + }; + this.img.src = this.attribute("xlink:href").value; + this.renderChildren = function (b) { + var c = this.attribute("x").Length.toPixels("x"), d = this.attribute("y").Length.toPixels("y"), f = this.attribute("width").Length.toPixels("x"), g = this.attribute("height").Length.toPixels("y"); + f == 0 || g == 0 || (b.save(), b.translate(c, d), a.AspectRatio(b, this.attribute("preserveAspectRatio").value, f, this.img.width, g, this.img.height, 0, 0), b.drawImage(this.img, 0, 0), b.restore()) + } + }; + a.Element.image.prototype = new a.Element.RenderedElementBase; + a.Element.g = function (c) { + this.base = a.Element.RenderedElementBase; + this.base(c); + this.getBoundingBox = function () { + for (var c = new a.BoundingBox, b = 0; b < this.children.length; b++)c.addBoundingBox(this.children[b].getBoundingBox()); + return c + } + }; + a.Element.g.prototype = new a.Element.RenderedElementBase; + a.Element.symbol = function (c) { + this.base = a.Element.RenderedElementBase; + this.base(c); + this.baseSetContext = this.setContext; + this.setContext = function (c) { + this.baseSetContext(c); + if (this.attribute("viewBox").hasValue()) { + var b = + a.ToNumberArray(this.attribute("viewBox").value), k = b[0], e = b[1]; + width = b[2]; + height = b[3]; + a.AspectRatio(c, this.attribute("preserveAspectRatio").value, this.attribute("width").Length.toPixels("x"), width, this.attribute("height").Length.toPixels("y"), height, k, e); + a.ViewPort.SetCurrent(b[2], b[3]) + } + } + }; + a.Element.symbol.prototype = new a.Element.RenderedElementBase; + a.Element.style = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + for (var c = c.childNodes[0].nodeValue + (c.childNodes.length > 1 ? c.childNodes[1].nodeValue : + ""), c = c.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, ""), c = a.compressSpaces(c), c = c.split("}"), d = 0; d < c.length; d++)if (a.trim(c[d]) != "")for (var b = c[d].split("{"), k = b[0].split(","), b = b[1].split(";"), e = 0; e < k.length; e++) { + var f = a.trim(k[e]); + if (f != "") { + for (var g = {}, j = 0; j < b.length; j++) { + var h = b[j].indexOf(":"), l = b[j].substr(0, h), h = b[j].substr(h + 1, b[j].length - h); + l != null && h != null && (g[a.trim(l)] = new a.Property(a.trim(l), a.trim(h))) + } + a.Styles[f] = g; + if (f == "@font-face") { + f = g["font-family"].value.replace(/"/g, + ""); + g = g.src.value.split(","); + for (j = 0; j < g.length; j++)if (g[j].indexOf('format("svg")') > 0) { + l = g[j].indexOf("url"); + h = g[j].indexOf(")", l); + l = g[j].substr(l + 5, h - l - 6); + l = a.parseXml(a.ajax(l)).getElementsByTagName("font"); + for (h = 0; h < l.length; h++) { + var o = a.CreateElement(l[h]); + a.Definitions[f] = o + } + } + } + } + } + }; + a.Element.style.prototype = new a.Element.ElementBase; + a.Element.use = function (c) { + this.base = a.Element.RenderedElementBase; + this.base(c); + this.baseSetContext = this.setContext; + this.setContext = function (a) { + this.baseSetContext(a); + this.attribute("x").hasValue() && a.translate(this.attribute("x").Length.toPixels("x"), 0); + this.attribute("y").hasValue() && a.translate(0, this.attribute("y").Length.toPixels("y")) + }; + this.getDefinition = function () { + var a = this.attribute("xlink:href").Definition.getDefinition(); + if (this.attribute("width").hasValue())a.attribute("width", !0).value = this.attribute("width").value; + if (this.attribute("height").hasValue())a.attribute("height", !0).value = this.attribute("height").value; + return a + }; + this.path = function (a) { + var b = + this.getDefinition(); + b != null && b.path(a) + }; + this.renderChildren = function (a) { + var b = this.getDefinition(); + b != null && b.render(a) + } + }; + a.Element.use.prototype = new a.Element.RenderedElementBase; + a.Element.mask = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.apply = function (a, b) { + var c = this.attribute("x").Length.toPixels("x"), e = this.attribute("y").Length.toPixels("y"), f = this.attribute("width").Length.toPixels("x"), g = this.attribute("height").Length.toPixels("y"), j = b.attribute("mask").value; + b.attribute("mask").value = + ""; + var h = document.createElement("canvas"); + h.width = c + f; + h.height = e + g; + var l = h.getContext("2d"); + this.renderChildren(l); + var o = document.createElement("canvas"); + o.width = c + f; + o.height = e + g; + var n = o.getContext("2d"); + b.render(n); + n.globalCompositeOperation = "destination-in"; + n.fillStyle = l.createPattern(h, "no-repeat"); + n.fillRect(0, 0, c + f, e + g); + a.fillStyle = n.createPattern(o, "no-repeat"); + a.fillRect(0, 0, c + f, e + g); + b.attribute("mask").value = j + }; + this.render = function () { + } + }; + a.Element.mask.prototype = new a.Element.ElementBase; + a.Element.clipPath = + function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.apply = function (a) { + for (var b = 0; b < this.children.length; b++)this.children[b].path && (this.children[b].path(a), a.clip()) + }; + this.render = function () { + } + }; + a.Element.clipPath.prototype = new a.Element.ElementBase; + a.Element.filter = function (c) { + this.base = a.Element.ElementBase; + this.base(c); + this.apply = function (a, b) { + var c = b.getBoundingBox(), e = this.attribute("x").Length.toPixels("x"), f = this.attribute("y").Length.toPixels("y"); + if (e == 0 || f == 0)e = c.x1, f = c.y1; + var g = + this.attribute("width").Length.toPixels("x"), j = this.attribute("height").Length.toPixels("y"); + if (g == 0 || j == 0)g = c.width(), j = c.height(); + c = b.style("filter").value; + b.style("filter").value = ""; + var h = 0.2 * g, l = 0.2 * j, o = document.createElement("canvas"); + o.width = g + 2 * h; + o.height = j + 2 * l; + var n = o.getContext("2d"); + n.translate(-e + h, -f + l); + b.render(n); + for (var q = 0; q < this.children.length; q++)this.children[q].apply(n, 0, 0, g + 2 * h, j + 2 * l); + a.drawImage(o, 0, 0, g + 2 * h, j + 2 * l, e - h, f - l, g + 2 * h, j + 2 * l); + b.style("filter", !0).value = c + }; + this.render = + function () { + } + }; + a.Element.filter.prototype = new a.Element.ElementBase; + a.Element.feGaussianBlur = function (c) { + function d(a, c, d, f, g) { + for (var j = 0; j < g; j++)for (var h = 0; h < f; h++)for (var l = a[j * f * 4 + h * 4 + 3] / 255, o = 0; o < 4; o++) { + for (var n = d[0] * (l == 0 ? 255 : a[j * f * 4 + h * 4 + o]) * (l == 0 || o == 3 ? 1 : l), q = 1; q < d.length; q++) { + var p = Math.max(h - q, 0), m = a[j * f * 4 + p * 4 + 3] / 255, p = Math.min(h + q, f - 1), p = a[j * f * 4 + p * 4 + 3] / 255, s = d[q], r; + m == 0 ? r = 255 : (r = Math.max(h - q, 0), r = a[j * f * 4 + r * 4 + o]); + m = r * (m == 0 || o == 3 ? 1 : m); + p == 0 ? r = 255 : (r = Math.min(h + q, f - 1), r = a[j * f * 4 + r * 4 + o]); + n += + s * (m + r * (p == 0 || o == 3 ? 1 : p)) + } + c[h * g * 4 + j * 4 + o] = n + } + } + + this.base = a.Element.ElementBase; + this.base(c); + this.apply = function (a, c, e, f, g) { + var e = this.attribute("stdDeviation").numValue(), c = a.getImageData(0, 0, f, g), e = Math.max(e, 0.01), j = Math.ceil(e * 4) + 1; + mask = []; + for (var h = 0; h < j; h++)mask[h] = Math.exp(-0.5 * (h / e) * (h / e)); + e = mask; + j = 0; + for (h = 1; h < e.length; h++)j += Math.abs(e[h]); + j = 2 * j + Math.abs(e[0]); + for (h = 0; h < e.length; h++)e[h] /= j; + tmp = []; + d(c.data, tmp, e, f, g); + d(tmp, c.data, e, g, f); + a.clearRect(0, 0, f, g); + a.putImageData(c, 0, 0) + } + }; + a.Element.filter.prototype = + new a.Element.feGaussianBlur; + a.Element.title = function () { + }; + a.Element.title.prototype = new a.Element.ElementBase; + a.Element.desc = function () { + }; + a.Element.desc.prototype = new a.Element.ElementBase; + a.Element.MISSING = function (a) { + console.log("ERROR: Element '" + a.nodeName + "' not yet implemented.") + }; + a.Element.MISSING.prototype = new a.Element.ElementBase; + a.CreateElement = function (c) { + var d = c.nodeName.replace(/^[^:]+:/, ""), d = d.replace(/\-/g, ""), b = null, b = typeof a.Element[d] != "undefined" ? new a.Element[d](c) : new a.Element.MISSING(c); + b.type = c.nodeName; + return b + }; + a.load = function (c, d) { + a.loadXml(c, a.ajax(d)) + }; + a.loadXml = function (c, d) { + a.loadXmlDoc(c, a.parseXml(d)) + }; + a.loadXmlDoc = function (c, d) { + a.init(c); + var b = function (a) { + for (var b = c.canvas; b;)a.x -= b.offsetLeft, a.y -= b.offsetTop, b = b.offsetParent; + window.scrollX && (a.x += window.scrollX); + window.scrollY && (a.y += window.scrollY); + return a + }; + if (a.opts.ignoreMouse != !0)c.canvas.onclick = function (c) { + c = b(new a.Point(c != null ? c.clientX : event.clientX, c != null ? c.clientY : event.clientY)); + a.Mouse.onclick(c.x, c.y) + }, + c.canvas.onmousemove = function (c) { + c = b(new a.Point(c != null ? c.clientX : event.clientX, c != null ? c.clientY : event.clientY)); + a.Mouse.onmousemove(c.x, c.y) + }; + var k = a.CreateElement(d.documentElement), e = k.root = !0, f = function () { + a.ViewPort.Clear(); + c.canvas.parentNode && a.ViewPort.SetCurrent(c.canvas.parentNode.clientWidth, c.canvas.parentNode.clientHeight); + if (a.opts.ignoreDimensions != !0) { + if (k.style("width").hasValue())c.canvas.width = k.style("width").Length.toPixels("x"), c.canvas.style.width = c.canvas.width + "px"; + if (k.style("height").hasValue())c.canvas.height = + k.style("height").Length.toPixels("y"), c.canvas.style.height = c.canvas.height + "px" + } + var b = c.canvas.clientWidth || c.canvas.width, d = c.canvas.clientHeight || c.canvas.height; + a.ViewPort.SetCurrent(b, d); + if (a.opts != null && a.opts.offsetX != null)k.attribute("x", !0).value = a.opts.offsetX; + if (a.opts != null && a.opts.offsetY != null)k.attribute("y", !0).value = a.opts.offsetY; + if (a.opts != null && a.opts.scaleWidth != null && a.opts.scaleHeight != null) { + var f = 1, g = 1; + k.attribute("width").hasValue() && (f = k.attribute("width").Length.toPixels("x") / + a.opts.scaleWidth); + k.attribute("height").hasValue() && (g = k.attribute("height").Length.toPixels("y") / a.opts.scaleHeight); + k.attribute("width", !0).value = a.opts.scaleWidth; + k.attribute("height", !0).value = a.opts.scaleHeight; + k.attribute("viewBox", !0).value = "0 0 " + b * f + " " + d * g; + k.attribute("preserveAspectRatio", !0).value = "none" + } + a.opts.ignoreClear != !0 && c.clearRect(0, 0, b, d); + k.render(c); + e && (e = !1, a.opts != null && typeof a.opts.renderCallback == "function" && a.opts.renderCallback()) + }, g = !0; + a.ImagesLoaded() && (g = !1, f()); + a.intervalID = setInterval(function () { + var b = !1; + g && a.ImagesLoaded() && (g = !1, b = !0); + a.opts.ignoreMouse != !0 && (b |= a.Mouse.hasEvents()); + if (a.opts.ignoreAnimation != !0)for (var c = 0; c < a.Animations.length; c++)b |= a.Animations[c].update(1E3 / a.FRAMERATE); + a.opts != null && typeof a.opts.forceRedraw == "function" && a.opts.forceRedraw() == !0 && (b = !0); + b && (f(), a.Mouse.runEvents()) + }, 1E3 / a.FRAMERATE) + }; + a.stop = function () { + a.intervalID && clearInterval(a.intervalID) + }; + a.Mouse = new function () { + this.events = []; + this.hasEvents = function () { + return this.events.length != + 0 + }; + this.onclick = function (a, d) { + this.events.push({type: "onclick", x: a, y: d, run: function (a) { + if (a.onclick)a.onclick() + }}) + }; + this.onmousemove = function (a, d) { + this.events.push({type: "onmousemove", x: a, y: d, run: function (a) { + if (a.onmousemove)a.onmousemove() + }}) + }; + this.eventElements = []; + this.checkPath = function (a, d) { + for (var b = 0; b < this.events.length; b++) { + var k = this.events[b]; + d.isPointInPath && d.isPointInPath(k.x, k.y) && (this.eventElements[b] = a) + } + }; + this.checkBoundingBox = function (a, d) { + for (var b = 0; b < this.events.length; b++) { + var k = + this.events[b]; + d.isPointInBox(k.x, k.y) && (this.eventElements[b] = a) + } + }; + this.runEvents = function () { + a.ctx.canvas.style.cursor = ""; + for (var c = 0; c < this.events.length; c++)for (var d = this.events[c], b = this.eventElements[c]; b;)d.run(b), b = b.parent; + this.events = []; + this.eventElements = [] + } + }; + return a + } + + this.canvg = function (a, c, d) { + if (a == null && c == null && d == null)for (var c = document.getElementsByTagName("svg"), b = 0; b < c.length; b++) { + a = c[b]; + d = document.createElement("canvas"); + d.width = a.clientWidth; + d.height = a.clientHeight; + a.parentNode.insertBefore(d, + a); + a.parentNode.removeChild(a); + var k = document.createElement("div"); + k.appendChild(a); + canvg(d, k.innerHTML) + } else d = d || {}, typeof a == "string" && (a = document.getElementById(a)), a.svg == null ? (b = m(), a.svg = b) : (b = a.svg, b.stop()), b.opts = d, a = a.getContext("2d"), typeof c.documentElement != "undefined" ? b.loadXmlDoc(a, c) : c.substr(0, 1) == "<" ? b.loadXml(a, c) : b.load(a, c) + } +})(); +if (CanvasRenderingContext2D)CanvasRenderingContext2D.prototype.drawSvg = function (m, a, c, d, b) { + canvg(this.canvas, m, {ignoreMouse: !0, ignoreAnimation: !0, ignoreDimensions: !0, ignoreClear: !0, offsetX: a, offsetY: c, scaleWidth: d, scaleHeight: b}) +}; +(function (m) { + var a = m.css, c = m.CanVGRenderer, d = m.SVGRenderer, b = m.extend, k = m.merge, e = m.addEvent, f = m.createElement, g = m.discardElement; + b(c.prototype, d.prototype); + b(c.prototype, {create: function (a, b, c, d) { + this.setContainer(b, c, d); + this.configure(a) + }, setContainer: function (a, b, c) { + var d = a.style, e = a.parentNode, g = d.left, d = d.top, k = a.offsetWidth, m = a.offsetHeight, s = {visibility: "hidden", position: "absolute"}; + this.init.apply(this, [a, b, c]); + this.canvas = f("canvas", {width: k, height: m}, {position: "relative", left: g, top: d}, a); + this.ttLine = f("div", null, s, e); + this.ttDiv = f("div", null, s, e); + this.ttTimer = void 0; + this.hiddenSvg = a = f("div", {width: k, height: m}, {visibility: "hidden", left: g, top: d}, e); + a.appendChild(this.box) + }, configure: function (b) { + var c = this, d = b.options.tooltip, f = d.borderWidth, g = c.ttDiv, m = d.style, p = c.ttLine, t = parseInt(m.padding, 10), m = k(m, {padding: t + "px", "background-color": d.backgroundColor, "border-style": "solid", "border-width": f + "px", "border-radius": d.borderRadius + "px"}); + d.shadow && (m = k(m, {"box-shadow": "1px 1px 3px gray", + "-webkit-box-shadow": "1px 1px 3px gray"})); + a(g, m); + a(p, {"border-left": "1px solid darkgray"}); + e(b, "tooltipRefresh", function (d) { + var e = b.container, f = e.offsetLeft, e = e.offsetTop, k; + g.innerHTML = d.text; + k = b.tooltip.getPosition(g.offsetWidth, g.offsetHeight, {plotX: d.x, plotY: d.y}); + a(g, {visibility: "visible", left: k.x + "px", top: k.y + "px", "border-color": d.borderColor}); + a(p, {visibility: "visible", left: f + d.x + "px", top: e + b.plotTop + "px", height: b.plotHeight + "px"}); + c.ttTimer !== void 0 && clearTimeout(c.ttTimer); + c.ttTimer = setTimeout(function () { + a(g, + {visibility: "hidden"}); + a(p, {visibility: "hidden"}) + }, 3E3) + }) + }, destroy: function () { + g(this.canvas); + this.ttTimer !== void 0 && clearTimeout(this.ttTimer); + g(this.ttLine); + g(this.ttDiv); + g(this.hiddenSvg); + return d.prototype.destroy.apply(this) + }, color: function (a, b, c) { + a && a.linearGradient && (a = a.stops[a.stops.length - 1][1]); + return d.prototype.color.call(this, a, b, c) + }, draw: function () { + window.canvg(this.canvas, this.hiddenSvg.innerHTML) + }}) +})(Highcharts); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/canvas-tools.src.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/canvas-tools.src.js new file mode 100644 index 0000000..f386940 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/canvas-tools.src.js @@ -0,0 +1,3187 @@ +/** + * @license A class to parse color values + * @author Stoyan Stefanov + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * Use it if you like it + * + */ +function RGBColor(color_string) { + this.ok = false; + + // strip any leading # + if (color_string.charAt(0) == '#') { // remove # if any + color_string = color_string.substr(1, 6); + } + + color_string = color_string.replace(/ /g, ''); + color_string = color_string.toLowerCase(); + + // before getting into regexps, try simple matches + // and overwrite the input + var simple_colors = { + aliceblue: 'f0f8ff', + antiquewhite: 'faebd7', + aqua: '00ffff', + aquamarine: '7fffd4', + azure: 'f0ffff', + beige: 'f5f5dc', + bisque: 'ffe4c4', + black: '000000', + blanchedalmond: 'ffebcd', + blue: '0000ff', + blueviolet: '8a2be2', + brown: 'a52a2a', + burlywood: 'deb887', + cadetblue: '5f9ea0', + chartreuse: '7fff00', + chocolate: 'd2691e', + coral: 'ff7f50', + cornflowerblue: '6495ed', + cornsilk: 'fff8dc', + crimson: 'dc143c', + cyan: '00ffff', + darkblue: '00008b', + darkcyan: '008b8b', + darkgoldenrod: 'b8860b', + darkgray: 'a9a9a9', + darkgreen: '006400', + darkkhaki: 'bdb76b', + darkmagenta: '8b008b', + darkolivegreen: '556b2f', + darkorange: 'ff8c00', + darkorchid: '9932cc', + darkred: '8b0000', + darksalmon: 'e9967a', + darkseagreen: '8fbc8f', + darkslateblue: '483d8b', + darkslategray: '2f4f4f', + darkturquoise: '00ced1', + darkviolet: '9400d3', + deeppink: 'ff1493', + deepskyblue: '00bfff', + dimgray: '696969', + dodgerblue: '1e90ff', + feldspar: 'd19275', + firebrick: 'b22222', + floralwhite: 'fffaf0', + forestgreen: '228b22', + fuchsia: 'ff00ff', + gainsboro: 'dcdcdc', + ghostwhite: 'f8f8ff', + gold: 'ffd700', + goldenrod: 'daa520', + gray: '808080', + green: '008000', + greenyellow: 'adff2f', + honeydew: 'f0fff0', + hotpink: 'ff69b4', + indianred: 'cd5c5c', + indigo: '4b0082', + ivory: 'fffff0', + khaki: 'f0e68c', + lavender: 'e6e6fa', + lavenderblush: 'fff0f5', + lawngreen: '7cfc00', + lemonchiffon: 'fffacd', + lightblue: 'add8e6', + lightcoral: 'f08080', + lightcyan: 'e0ffff', + lightgoldenrodyellow: 'fafad2', + lightgrey: 'd3d3d3', + lightgreen: '90ee90', + lightpink: 'ffb6c1', + lightsalmon: 'ffa07a', + lightseagreen: '20b2aa', + lightskyblue: '87cefa', + lightslateblue: '8470ff', + lightslategray: '778899', + lightsteelblue: 'b0c4de', + lightyellow: 'ffffe0', + lime: '00ff00', + limegreen: '32cd32', + linen: 'faf0e6', + magenta: 'ff00ff', + maroon: '800000', + mediumaquamarine: '66cdaa', + mediumblue: '0000cd', + mediumorchid: 'ba55d3', + mediumpurple: '9370d8', + mediumseagreen: '3cb371', + mediumslateblue: '7b68ee', + mediumspringgreen: '00fa9a', + mediumturquoise: '48d1cc', + mediumvioletred: 'c71585', + midnightblue: '191970', + mintcream: 'f5fffa', + mistyrose: 'ffe4e1', + moccasin: 'ffe4b5', + navajowhite: 'ffdead', + navy: '000080', + oldlace: 'fdf5e6', + olive: '808000', + olivedrab: '6b8e23', + orange: 'ffa500', + orangered: 'ff4500', + orchid: 'da70d6', + palegoldenrod: 'eee8aa', + palegreen: '98fb98', + paleturquoise: 'afeeee', + palevioletred: 'd87093', + papayawhip: 'ffefd5', + peachpuff: 'ffdab9', + peru: 'cd853f', + pink: 'ffc0cb', + plum: 'dda0dd', + powderblue: 'b0e0e6', + purple: '800080', + red: 'ff0000', + rosybrown: 'bc8f8f', + royalblue: '4169e1', + saddlebrown: '8b4513', + salmon: 'fa8072', + sandybrown: 'f4a460', + seagreen: '2e8b57', + seashell: 'fff5ee', + sienna: 'a0522d', + silver: 'c0c0c0', + skyblue: '87ceeb', + slateblue: '6a5acd', + slategray: '708090', + snow: 'fffafa', + springgreen: '00ff7f', + steelblue: '4682b4', + tan: 'd2b48c', + teal: '008080', + thistle: 'd8bfd8', + tomato: 'ff6347', + turquoise: '40e0d0', + violet: 'ee82ee', + violetred: 'd02090', + wheat: 'f5deb3', + white: 'ffffff', + whitesmoke: 'f5f5f5', + yellow: 'ffff00', + yellowgreen: '9acd32' + }; + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } + // emd of simple type-in colors + + // array of color definition objects + var color_defs = [ + { + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], + process: function (bits) { + return [ + parseInt(bits[1]), + parseInt(bits[2]), + parseInt(bits[3]) + ]; + } + }, + { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ['#00ff00', '336699'], + process: function (bits) { + return [ + parseInt(bits[1], 16), + parseInt(bits[2], 16), + parseInt(bits[3], 16) + ]; + } + }, + { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ['#fb0', 'f0f'], + process: function (bits) { + return [ + parseInt(bits[1] + bits[1], 16), + parseInt(bits[2] + bits[2], 16), + parseInt(bits[3] + bits[3], 16) + ]; + } + } + ]; + + // search through the definitions to find a match + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + if (bits) { + channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + + } + + // validate/cleanup values + this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); + this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); + this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); + + // some getters + this.toRGB = function () { + return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; + } + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = '0' + r; + if (g.length == 1) g = '0' + g; + if (b.length == 1) b = '0' + b; + return '#' + r + g + b; + } + + // help + this.getHelpXML = function () { + + var examples = new Array(); + // add regexps + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } + // add type-in colors + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + + var xml = document.createElement('ul'); + xml.setAttribute('id', 'rgbcolor-examples'); + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement('li'); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement('div'); + example_div.style.cssText = + 'margin: 3px; ' + + 'border: 1px solid black; ' + + 'background:' + list_color.toHex() + '; ' + + 'color:' + list_color.toHex() + ; + example_div.appendChild(document.createTextNode('test')); + var list_item_value = document.createTextNode( + ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex() + ); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + + } catch (e) { + } + } + return xml; + + } + +} + +/** + * @license canvg.js - Javascript SVG parser and renderer on Canvas + * MIT Licensed + * Gabe Lerner (gabelerner@gmail.com) + * http://code.google.com/p/canvg/ + * + * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/ + * + */ +if (!window.console) { + window.console = {}; + window.console.log = function (str) { + }; + window.console.dir = function (str) { + }; +} + +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (obj) { + for (var i = 0; i < this.length; i++) { + if (this[i] == obj) { + return i; + } + } + return -1; + } +} + +(function () { + // canvg(target, s) + // empty parameters: replace all 'svg' elements on page with 'canvas' elements + // target: canvas element or the id of a canvas element + // s: svg string, url to svg file, or xml document + // opts: optional hash of options + // ignoreMouse: true => ignore mouse events + // ignoreAnimation: true => ignore animations + // ignoreDimensions: true => does not try to resize canvas + // ignoreClear: true => does not clear canvas + // offsetX: int => draws at a x offset + // offsetY: int => draws at a y offset + // scaleWidth: int => scales horizontally to width + // scaleHeight: int => scales vertically to height + // renderCallback: function => will call the function after the first render is completed + // forceRedraw: function => will call the function on every frame, if it returns true, will redraw + this.canvg = function (target, s, opts) { + // no parameters + if (target == null && s == null && opts == null) { + var svgTags = document.getElementsByTagName('svg'); + for (var i = 0; i < svgTags.length; i++) { + var svgTag = svgTags[i]; + var c = document.createElement('canvas'); + c.width = svgTag.clientWidth; + c.height = svgTag.clientHeight; + svgTag.parentNode.insertBefore(c, svgTag); + svgTag.parentNode.removeChild(svgTag); + var div = document.createElement('div'); + div.appendChild(svgTag); + canvg(c, div.innerHTML); + } + return; + } + opts = opts || {}; + + if (typeof target == 'string') { + target = document.getElementById(target); + } + + // reuse class per canvas + var svg; + if (target.svg == null) { + svg = build(); + target.svg = svg; + } + else { + svg = target.svg; + svg.stop(); + } + svg.opts = opts; + + var ctx = target.getContext('2d'); + if (typeof(s.documentElement) != 'undefined') { + // load from xml doc + svg.loadXmlDoc(ctx, s); + } + else if (s.substr(0, 1) == '<') { + // load from xml string + svg.loadXml(ctx, s); + } + else { + // load from url + svg.load(ctx, s); + } + } + + function build() { + var svg = { }; + + svg.FRAMERATE = 30; + svg.MAX_VIRTUAL_PIXELS = 30000; + + // globals + svg.init = function (ctx) { + svg.Definitions = {}; + svg.Styles = {}; + svg.Animations = []; + svg.Images = []; + svg.ctx = ctx; + svg.ViewPort = new (function () { + this.viewPorts = []; + this.Clear = function () { + this.viewPorts = []; + } + this.SetCurrent = function (width, height) { + this.viewPorts.push({ width: width, height: height }); + } + this.RemoveCurrent = function () { + this.viewPorts.pop(); + } + this.Current = function () { + return this.viewPorts[this.viewPorts.length - 1]; + } + this.width = function () { + return this.Current().width; + } + this.height = function () { + return this.Current().height; + } + this.ComputeSize = function (d) { + if (d != null && typeof(d) == 'number') return d; + if (d == 'x') return this.width(); + if (d == 'y') return this.height(); + return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2); + } + }); + } + svg.init(); + + // images loaded + svg.ImagesLoaded = function () { + for (var i = 0; i < svg.Images.length; i++) { + if (!svg.Images[i].loaded) return false; + } + return true; + } + + // trim + svg.trim = function (s) { + return s.replace(/^\s+|\s+$/g, ''); + } + + // compress spaces + svg.compressSpaces = function (s) { + return s.replace(/[\s\r\t\n]+/gm, ' '); + } + + // ajax + svg.ajax = function (url) { + var AJAX; + if (window.XMLHttpRequest) { + AJAX = new XMLHttpRequest(); + } + else { + AJAX = new ActiveXObject('Microsoft.XMLHTTP'); + } + if (AJAX) { + AJAX.open('GET', url, false); + AJAX.send(null); + return AJAX.responseText; + } + return null; + } + + // parse xml + svg.parseXml = function (xml) { + if (window.DOMParser) { + var parser = new DOMParser(); + return parser.parseFromString(xml, 'text/xml'); + } + else { + xml = xml.replace(/]*>/, ''); + var xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); + xmlDoc.async = 'false'; + xmlDoc.loadXML(xml); + return xmlDoc; + } + } + + svg.Property = function (name, value) { + this.name = name; + this.value = value; + + this.hasValue = function () { + return (this.value != null && this.value !== ''); + } + + // return the numerical value of the property + this.numValue = function () { + if (!this.hasValue()) return 0; + + var n = parseFloat(this.value); + if ((this.value + '').match(/%$/)) { + n = n / 100.0; + } + return n; + } + + this.valueOrDefault = function (def) { + if (this.hasValue()) return this.value; + return def; + } + + this.numValueOrDefault = function (def) { + if (this.hasValue()) return this.numValue(); + return def; + } + + /* EXTENSIONS */ + var that = this; + + // color extensions + this.Color = { + // augment the current color value with the opacity + addOpacity: function (opacity) { + var newValue = that.value; + if (opacity != null && opacity != '') { + var color = new RGBColor(that.value); + if (color.ok) { + newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacity + ')'; + } + } + return new svg.Property(that.name, newValue); + } + } + + // definition extensions + this.Definition = { + // get the definition from the definitions table + getDefinition: function () { + var name = that.value.replace(/^(url\()?#([^\)]+)\)?$/, '$2'); + return svg.Definitions[name]; + }, + + isUrl: function () { + return that.value.indexOf('url(') == 0 + }, + + getFillStyle: function (e) { + var def = this.getDefinition(); + + // gradient + if (def != null && def.createGradient) { + return def.createGradient(svg.ctx, e); + } + + // pattern + if (def != null && def.createPattern) { + return def.createPattern(svg.ctx, e); + } + + return null; + } + } + + // length extensions + this.Length = { + DPI: function (viewPort) { + return 96.0; // TODO: compute? + }, + + EM: function (viewPort) { + var em = 12; + + var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize); + if (fontSize.hasValue()) em = fontSize.Length.toPixels(viewPort); + + return em; + }, + + // get the length as pixels + toPixels: function (viewPort) { + if (!that.hasValue()) return 0; + var s = that.value + ''; + if (s.match(/em$/)) return that.numValue() * this.EM(viewPort); + if (s.match(/ex$/)) return that.numValue() * this.EM(viewPort) / 2.0; + if (s.match(/px$/)) return that.numValue(); + if (s.match(/pt$/)) return that.numValue() * 1.25; + if (s.match(/pc$/)) return that.numValue() * 15; + if (s.match(/cm$/)) return that.numValue() * this.DPI(viewPort) / 2.54; + if (s.match(/mm$/)) return that.numValue() * this.DPI(viewPort) / 25.4; + if (s.match(/in$/)) return that.numValue() * this.DPI(viewPort); + if (s.match(/%$/)) return that.numValue() * svg.ViewPort.ComputeSize(viewPort); + return that.numValue(); + } + } + + // time extensions + this.Time = { + // get the time as milliseconds + toMilliseconds: function () { + if (!that.hasValue()) return 0; + var s = that.value + ''; + if (s.match(/s$/)) return that.numValue() * 1000; + if (s.match(/ms$/)) return that.numValue(); + return that.numValue(); + } + } + + // angle extensions + this.Angle = { + // get the angle as radians + toRadians: function () { + if (!that.hasValue()) return 0; + var s = that.value + ''; + if (s.match(/deg$/)) return that.numValue() * (Math.PI / 180.0); + if (s.match(/grad$/)) return that.numValue() * (Math.PI / 200.0); + if (s.match(/rad$/)) return that.numValue(); + return that.numValue() * (Math.PI / 180.0); + } + } + } + + // fonts + svg.Font = new (function () { + this.Styles = ['normal', 'italic', 'oblique', 'inherit']; + this.Variants = ['normal', 'small-caps', 'inherit']; + this.Weights = ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900', 'inherit']; + + this.CreateFont = function (fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) { + var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font); + return { + fontFamily: fontFamily || f.fontFamily, + fontSize: fontSize || f.fontSize, + fontStyle: fontStyle || f.fontStyle, + fontWeight: fontWeight || f.fontWeight, + fontVariant: fontVariant || f.fontVariant, + toString: function () { + return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') + } + } + } + + var that = this; + this.Parse = function (s) { + var f = {}; + var d = svg.trim(svg.compressSpaces(s || '')).split(' '); + var set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false } + var ff = ''; + for (var i = 0; i < d.length; i++) { + if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) { + if (d[i] != 'inherit') f.fontStyle = d[i]; + set.fontStyle = true; + } + else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) { + if (d[i] != 'inherit') f.fontVariant = d[i]; + set.fontStyle = set.fontVariant = true; + } + else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) { + if (d[i] != 'inherit') f.fontWeight = d[i]; + set.fontStyle = set.fontVariant = set.fontWeight = true; + } + else if (!set.fontSize) { + if (d[i] != 'inherit') f.fontSize = d[i].split('/')[0]; + set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true; + } + else { + if (d[i] != 'inherit') ff += d[i]; + } + } + if (ff != '') f.fontFamily = ff; + return f; + } + }); + + // points and paths + svg.ToNumberArray = function (s) { + var a = svg.trim(svg.compressSpaces((s || '').replace(/,/g, ' '))).split(' '); + for (var i = 0; i < a.length; i++) { + a[i] = parseFloat(a[i]); + } + return a; + } + svg.Point = function (x, y) { + this.x = x; + this.y = y; + + this.angleTo = function (p) { + return Math.atan2(p.y - this.y, p.x - this.x); + } + + this.applyTransform = function (v) { + var xp = this.x * v[0] + this.y * v[2] + v[4]; + var yp = this.x * v[1] + this.y * v[3] + v[5]; + this.x = xp; + this.y = yp; + } + } + svg.CreatePoint = function (s) { + var a = svg.ToNumberArray(s); + return new svg.Point(a[0], a[1]); + } + svg.CreatePath = function (s) { + var a = svg.ToNumberArray(s); + var path = []; + for (var i = 0; i < a.length; i += 2) { + path.push(new svg.Point(a[i], a[i + 1])); + } + return path; + } + + // bounding box + svg.BoundingBox = function (x1, y1, x2, y2) { // pass in initial points if you want + this.x1 = Number.NaN; + this.y1 = Number.NaN; + this.x2 = Number.NaN; + this.y2 = Number.NaN; + + this.x = function () { + return this.x1; + } + this.y = function () { + return this.y1; + } + this.width = function () { + return this.x2 - this.x1; + } + this.height = function () { + return this.y2 - this.y1; + } + + this.addPoint = function (x, y) { + if (x != null) { + if (isNaN(this.x1) || isNaN(this.x2)) { + this.x1 = x; + this.x2 = x; + } + if (x < this.x1) this.x1 = x; + if (x > this.x2) this.x2 = x; + } + + if (y != null) { + if (isNaN(this.y1) || isNaN(this.y2)) { + this.y1 = y; + this.y2 = y; + } + if (y < this.y1) this.y1 = y; + if (y > this.y2) this.y2 = y; + } + } + this.addX = function (x) { + this.addPoint(x, null); + } + this.addY = function (y) { + this.addPoint(null, y); + } + + this.addBoundingBox = function (bb) { + this.addPoint(bb.x1, bb.y1); + this.addPoint(bb.x2, bb.y2); + } + + this.addQuadraticCurve = function (p0x, p0y, p1x, p1y, p2x, p2y) { + var cp1x = p0x + 2 / 3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp1y = p0y + 2 / 3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp2x = cp1x + 1 / 3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0) + var cp2y = cp1y + 1 / 3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0) + this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y); + } + + this.addBezierCurve = function (p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) { + // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + var p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y]; + this.addPoint(p0[0], p0[1]); + this.addPoint(p3[0], p3[1]); + + for (i = 0; i <= 1; i++) { + var f = function (t) { + return Math.pow(1 - t, 3) * p0[i] + + 3 * Math.pow(1 - t, 2) * t * p1[i] + + 3 * (1 - t) * Math.pow(t, 2) * p2[i] + + Math.pow(t, 3) * p3[i]; + } + + var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i]; + var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i]; + var c = 3 * p1[i] - 3 * p0[i]; + + if (a == 0) { + if (b == 0) continue; + var t = -c / b; + if (0 < t && t < 1) { + if (i == 0) this.addX(f(t)); + if (i == 1) this.addY(f(t)); + } + continue; + } + + var b2ac = Math.pow(b, 2) - 4 * c * a; + if (b2ac < 0) continue; + var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); + if (0 < t1 && t1 < 1) { + if (i == 0) this.addX(f(t1)); + if (i == 1) this.addY(f(t1)); + } + var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); + if (0 < t2 && t2 < 1) { + if (i == 0) this.addX(f(t2)); + if (i == 1) this.addY(f(t2)); + } + } + } + + this.isPointInBox = function (x, y) { + return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2); + } + + this.addPoint(x1, y1); + this.addPoint(x2, y2); + } + + // transforms + svg.Transform = function (v) { + var that = this; + this.Type = {} + + // translate + this.Type.translate = function (s) { + this.p = svg.CreatePoint(s); + this.apply = function (ctx) { + ctx.translate(this.p.x || 0.0, this.p.y || 0.0); + } + this.applyToPoint = function (p) { + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]); + } + } + + // rotate + this.Type.rotate = function (s) { + var a = svg.ToNumberArray(s); + this.angle = new svg.Property('angle', a[0]); + this.cx = a[1] || 0; + this.cy = a[2] || 0; + this.apply = function (ctx) { + ctx.translate(this.cx, this.cy); + ctx.rotate(this.angle.Angle.toRadians()); + ctx.translate(-this.cx, -this.cy); + } + this.applyToPoint = function (p) { + var a = this.angle.Angle.toRadians(); + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]); + p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]); + p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]); + } + } + + this.Type.scale = function (s) { + this.p = svg.CreatePoint(s); + this.apply = function (ctx) { + ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0); + } + this.applyToPoint = function (p) { + p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]); + } + } + + this.Type.matrix = function (s) { + this.m = svg.ToNumberArray(s); + this.apply = function (ctx) { + ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]); + } + this.applyToPoint = function (p) { + p.applyTransform(this.m); + } + } + + this.Type.SkewBase = function (s) { + this.base = that.Type.matrix; + this.base(s); + this.angle = new svg.Property('angle', s); + } + this.Type.SkewBase.prototype = new this.Type.matrix; + + this.Type.skewX = function (s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [1, 0, Math.tan(this.angle.Angle.toRadians()), 1, 0, 0]; + } + this.Type.skewX.prototype = new this.Type.SkewBase; + + this.Type.skewY = function (s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [1, Math.tan(this.angle.Angle.toRadians()), 0, 1, 0, 0]; + } + this.Type.skewY.prototype = new this.Type.SkewBase; + + this.transforms = []; + + this.apply = function (ctx) { + for (var i = 0; i < this.transforms.length; i++) { + this.transforms[i].apply(ctx); + } + } + + this.applyToPoint = function (p) { + for (var i = 0; i < this.transforms.length; i++) { + this.transforms[i].applyToPoint(p); + } + } + + var data = svg.trim(svg.compressSpaces(v)).split(/\s(?=[a-z])/); + for (var i = 0; i < data.length; i++) { + var type = data[i].split('(')[0]; + var s = data[i].split('(')[1].replace(')', ''); + var transform = new this.Type[type](s); + this.transforms.push(transform); + } + } + + // aspect ratio + svg.AspectRatio = function (ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) { + // aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute + aspectRatio = svg.compressSpaces(aspectRatio); + aspectRatio = aspectRatio.replace(/^defer\s/, ''); // ignore defer + var align = aspectRatio.split(' ')[0] || 'xMidYMid'; + var meetOrSlice = aspectRatio.split(' ')[1] || 'meet'; + + // calculate scale + var scaleX = width / desiredWidth; + var scaleY = height / desiredHeight; + var scaleMin = Math.min(scaleX, scaleY); + var scaleMax = Math.max(scaleX, scaleY); + if (meetOrSlice == 'meet') { + desiredWidth *= scaleMin; + desiredHeight *= scaleMin; + } + if (meetOrSlice == 'slice') { + desiredWidth *= scaleMax; + desiredHeight *= scaleMax; + } + + refX = new svg.Property('refX', refX); + refY = new svg.Property('refY', refY); + if (refX.hasValue() && refY.hasValue()) { + ctx.translate(-scaleMin * refX.Length.toPixels('x'), -scaleMin * refY.Length.toPixels('y')); + } + else { + // align + if (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width / 2.0 - desiredWidth / 2.0, 0); + if (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height / 2.0 - desiredHeight / 2.0); + if (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width - desiredWidth, 0); + if (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height - desiredHeight); + } + + // scale + if (align == 'none') ctx.scale(scaleX, scaleY); + else if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin); + else if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax); + + // translate + ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY); + } + + // elements + svg.Element = {} + + svg.Element.ElementBase = function (node) { + this.attributes = {}; + this.styles = {}; + this.children = []; + + // get or create attribute + this.attribute = function (name, createIfNotExists) { + var a = this.attributes[name]; + if (a != null) return a; + + a = new svg.Property(name, ''); + if (createIfNotExists == true) this.attributes[name] = a; + return a; + } + + // get or create style, crawls up node tree + this.style = function (name, createIfNotExists) { + var s = this.styles[name]; + if (s != null) return s; + + var a = this.attribute(name); + if (a != null && a.hasValue()) { + return a; + } + + var p = this.parent; + if (p != null) { + var ps = p.style(name); + if (ps != null && ps.hasValue()) { + return ps; + } + } + + s = new svg.Property(name, ''); + if (createIfNotExists == true) this.styles[name] = s; + return s; + } + + // base render + this.render = function (ctx) { + // don't render display=none + if (this.style('display').value == 'none') return; + + // don't render visibility=hidden + if (this.attribute('visibility').value == 'hidden') return; + + ctx.save(); + this.setContext(ctx); + // mask + if (this.attribute('mask').hasValue()) { + var mask = this.attribute('mask').Definition.getDefinition(); + if (mask != null) mask.apply(ctx, this); + } + else if (this.style('filter').hasValue()) { + var filter = this.style('filter').Definition.getDefinition(); + if (filter != null) filter.apply(ctx, this); + } + else this.renderChildren(ctx); + this.clearContext(ctx); + ctx.restore(); + } + + // base set context + this.setContext = function (ctx) { + // OVERRIDE ME! + } + + // base clear context + this.clearContext = function (ctx) { + // OVERRIDE ME! + } + + // base render children + this.renderChildren = function (ctx) { + for (var i = 0; i < this.children.length; i++) { + this.children[i].render(ctx); + } + } + + this.addChild = function (childNode, create) { + var child = childNode; + if (create) child = svg.CreateElement(childNode); + child.parent = this; + this.children.push(child); + } + + if (node != null && node.nodeType == 1) { //ELEMENT_NODE + // add children + for (var i = 0; i < node.childNodes.length; i++) { + var childNode = node.childNodes[i]; + if (childNode.nodeType == 1) this.addChild(childNode, true); //ELEMENT_NODE + } + + // add attributes + for (var i = 0; i < node.attributes.length; i++) { + var attribute = node.attributes[i]; + this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue); + } + + // add tag styles + var styles = svg.Styles[node.nodeName]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + + // add class styles + if (this.attribute('class').hasValue()) { + var classes = svg.compressSpaces(this.attribute('class').value).split(' '); + for (var j = 0; j < classes.length; j++) { + styles = svg.Styles['.' + classes[j]]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + styles = svg.Styles[node.nodeName + '.' + classes[j]]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + } + } + + // add inline styles + if (this.attribute('style').hasValue()) { + var styles = this.attribute('style').value.split(';'); + for (var i = 0; i < styles.length; i++) { + if (svg.trim(styles[i]) != '') { + var style = styles[i].split(':'); + var name = svg.trim(style[0]); + var value = svg.trim(style[1]); + this.styles[name] = new svg.Property(name, value); + } + } + } + + // add id + if (this.attribute('id').hasValue()) { + if (svg.Definitions[this.attribute('id').value] == null) { + svg.Definitions[this.attribute('id').value] = this; + } + } + } + } + + svg.Element.RenderedElementBase = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.setContext = function (ctx) { + // fill + if (this.style('fill').Definition.isUrl()) { + var fs = this.style('fill').Definition.getFillStyle(this); + if (fs != null) ctx.fillStyle = fs; + } + else if (this.style('fill').hasValue()) { + var fillStyle = this.style('fill'); + if (this.style('fill-opacity').hasValue()) fillStyle = fillStyle.Color.addOpacity(this.style('fill-opacity').value); + ctx.fillStyle = (fillStyle.value == 'none' ? 'rgba(0,0,0,0)' : fillStyle.value); + } + + // stroke + if (this.style('stroke').Definition.isUrl()) { + var fs = this.style('stroke').Definition.getFillStyle(this); + if (fs != null) ctx.strokeStyle = fs; + } + else if (this.style('stroke').hasValue()) { + var strokeStyle = this.style('stroke'); + if (this.style('stroke-opacity').hasValue()) strokeStyle = strokeStyle.Color.addOpacity(this.style('stroke-opacity').value); + ctx.strokeStyle = (strokeStyle.value == 'none' ? 'rgba(0,0,0,0)' : strokeStyle.value); + } + if (this.style('stroke-width').hasValue()) ctx.lineWidth = this.style('stroke-width').Length.toPixels(); + if (this.style('stroke-linecap').hasValue()) ctx.lineCap = this.style('stroke-linecap').value; + if (this.style('stroke-linejoin').hasValue()) ctx.lineJoin = this.style('stroke-linejoin').value; + if (this.style('stroke-miterlimit').hasValue()) ctx.miterLimit = this.style('stroke-miterlimit').value; + + // font + if (typeof(ctx.font) != 'undefined') { + ctx.font = svg.Font.CreateFont( + this.style('font-style').value, + this.style('font-variant').value, + this.style('font-weight').value, + this.style('font-size').hasValue() ? this.style('font-size').Length.toPixels() + 'px' : '', + this.style('font-family').value).toString(); + } + + // transform + if (this.attribute('transform').hasValue()) { + var transform = new svg.Transform(this.attribute('transform').value); + transform.apply(ctx); + } + + // clip + if (this.attribute('clip-path').hasValue()) { + var clip = this.attribute('clip-path').Definition.getDefinition(); + if (clip != null) clip.apply(ctx); + } + + // opacity + if (this.style('opacity').hasValue()) { + ctx.globalAlpha = this.style('opacity').numValue(); + } + } + } + svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase; + + svg.Element.PathElementBase = function (node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.path = function (ctx) { + if (ctx != null) ctx.beginPath(); + return new svg.BoundingBox(); + } + + this.renderChildren = function (ctx) { + this.path(ctx); + svg.Mouse.checkPath(this, ctx); + if (ctx.fillStyle != '') ctx.fill(); + if (ctx.strokeStyle != '') ctx.stroke(); + + var markers = this.getMarkers(); + if (markers != null) { + if (this.style('marker-start').Definition.isUrl()) { + var marker = this.style('marker-start').Definition.getDefinition(); + marker.render(ctx, markers[0][0], markers[0][1]); + } + if (this.style('marker-mid').Definition.isUrl()) { + var marker = this.style('marker-mid').Definition.getDefinition(); + for (var i = 1; i < markers.length - 1; i++) { + marker.render(ctx, markers[i][0], markers[i][1]); + } + } + if (this.style('marker-end').Definition.isUrl()) { + var marker = this.style('marker-end').Definition.getDefinition(); + marker.render(ctx, markers[markers.length - 1][0], markers[markers.length - 1][1]); + } + } + } + + this.getBoundingBox = function () { + return this.path(); + } + + this.getMarkers = function () { + return null; + } + } + svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase; + + // svg element + svg.Element.svg = function (node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.baseClearContext = this.clearContext; + this.clearContext = function (ctx) { + this.baseClearContext(ctx); + svg.ViewPort.RemoveCurrent(); + } + + this.baseSetContext = this.setContext; + this.setContext = function (ctx) { + // initial values + ctx.strokeStyle = 'rgba(0,0,0,0)'; + ctx.lineCap = 'butt'; + ctx.lineJoin = 'miter'; + ctx.miterLimit = 4; + + this.baseSetContext(ctx); + + // create new view port + if (this.attribute('x').hasValue() && this.attribute('y').hasValue()) { + ctx.translate(this.attribute('x').Length.toPixels('x'), this.attribute('y').Length.toPixels('y')); + } + + var width = svg.ViewPort.width(); + var height = svg.ViewPort.height(); + if (typeof(this.root) == 'undefined' && this.attribute('width').hasValue() && this.attribute('height').hasValue()) { + width = this.attribute('width').Length.toPixels('x'); + height = this.attribute('height').Length.toPixels('y'); + + var x = 0; + var y = 0; + if (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) { + x = -this.attribute('refX').Length.toPixels('x'); + y = -this.attribute('refY').Length.toPixels('y'); + } + + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineTo(width, y); + ctx.lineTo(width, height); + ctx.lineTo(x, height); + ctx.closePath(); + ctx.clip(); + } + svg.ViewPort.SetCurrent(width, height); + + // viewbox + if (this.attribute('viewBox').hasValue()) { + var viewBox = svg.ToNumberArray(this.attribute('viewBox').value); + var minX = viewBox[0]; + var minY = viewBox[1]; + width = viewBox[2]; + height = viewBox[3]; + + svg.AspectRatio(ctx, + this.attribute('preserveAspectRatio').value, + svg.ViewPort.width(), + width, + svg.ViewPort.height(), + height, + minX, + minY, + this.attribute('refX').value, + this.attribute('refY').value); + + svg.ViewPort.RemoveCurrent(); + svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]); + } + } + } + svg.Element.svg.prototype = new svg.Element.RenderedElementBase; + + // rect element + svg.Element.rect = function (node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.path = function (ctx) { + var x = this.attribute('x').Length.toPixels('x'); + var y = this.attribute('y').Length.toPixels('y'); + var width = this.attribute('width').Length.toPixels('x'); + var height = this.attribute('height').Length.toPixels('y'); + var rx = this.attribute('rx').Length.toPixels('x'); + var ry = this.attribute('ry').Length.toPixels('y'); + if (this.attribute('rx').hasValue() && !this.attribute('ry').hasValue()) ry = rx; + if (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry; + + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(x + rx, y); + ctx.lineTo(x + width - rx, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + ry) + ctx.lineTo(x + width, y + height - ry); + ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height) + ctx.lineTo(x + rx, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - ry) + ctx.lineTo(x, y + ry); + ctx.quadraticCurveTo(x, y, x + rx, y) + ctx.closePath(); + } + + return new svg.BoundingBox(x, y, x + width, y + height); + } + } + svg.Element.rect.prototype = new svg.Element.PathElementBase; + + // circle element + svg.Element.circle = function (node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.path = function (ctx) { + var cx = this.attribute('cx').Length.toPixels('x'); + var cy = this.attribute('cy').Length.toPixels('y'); + var r = this.attribute('r').Length.toPixels(); + + if (ctx != null) { + ctx.beginPath(); + ctx.arc(cx, cy, r, 0, Math.PI * 2, true); + ctx.closePath(); + } + + return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r); + } + } + svg.Element.circle.prototype = new svg.Element.PathElementBase; + + // ellipse element + svg.Element.ellipse = function (node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.path = function (ctx) { + var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3); + var rx = this.attribute('rx').Length.toPixels('x'); + var ry = this.attribute('ry').Length.toPixels('y'); + var cx = this.attribute('cx').Length.toPixels('x'); + var cy = this.attribute('cy').Length.toPixels('y'); + + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(cx, cy - ry); + ctx.bezierCurveTo(cx + (KAPPA * rx), cy - ry, cx + rx, cy - (KAPPA * ry), cx + rx, cy); + ctx.bezierCurveTo(cx + rx, cy + (KAPPA * ry), cx + (KAPPA * rx), cy + ry, cx, cy + ry); + ctx.bezierCurveTo(cx - (KAPPA * rx), cy + ry, cx - rx, cy + (KAPPA * ry), cx - rx, cy); + ctx.bezierCurveTo(cx - rx, cy - (KAPPA * ry), cx - (KAPPA * rx), cy - ry, cx, cy - ry); + ctx.closePath(); + } + + return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry); + } + } + svg.Element.ellipse.prototype = new svg.Element.PathElementBase; + + // line element + svg.Element.line = function (node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.getPoints = function () { + return [ + new svg.Point(this.attribute('x1').Length.toPixels('x'), this.attribute('y1').Length.toPixels('y')), + new svg.Point(this.attribute('x2').Length.toPixels('x'), this.attribute('y2').Length.toPixels('y'))]; + } + + this.path = function (ctx) { + var points = this.getPoints(); + + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(points[0].x, points[0].y); + ctx.lineTo(points[1].x, points[1].y); + } + + return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y); + } + + this.getMarkers = function () { + var points = this.getPoints(); + var a = points[0].angleTo(points[1]); + return [ + [points[0], a], + [points[1], a] + ]; + } + } + svg.Element.line.prototype = new svg.Element.PathElementBase; + + // polyline element + svg.Element.polyline = function (node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.points = svg.CreatePath(this.attribute('points').value); + this.path = function (ctx) { + var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y); + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + } + for (var i = 1; i < this.points.length; i++) { + bb.addPoint(this.points[i].x, this.points[i].y); + if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y); + } + return bb; + } + + this.getMarkers = function () { + var markers = []; + for (var i = 0; i < this.points.length - 1; i++) { + markers.push([this.points[i], this.points[i].angleTo(this.points[i + 1])]); + } + markers.push([this.points[this.points.length - 1], markers[markers.length - 1][1]]); + return markers; + } + } + svg.Element.polyline.prototype = new svg.Element.PathElementBase; + + // polygon element + svg.Element.polygon = function (node) { + this.base = svg.Element.polyline; + this.base(node); + + this.basePath = this.path; + this.path = function (ctx) { + var bb = this.basePath(ctx); + if (ctx != null) { + ctx.lineTo(this.points[0].x, this.points[0].y); + ctx.closePath(); + } + return bb; + } + } + svg.Element.polygon.prototype = new svg.Element.polyline; + + // path element + svg.Element.path = function (node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + var d = this.attribute('d').value; + // TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF + d = d.replace(/,/gm, ' '); // get rid of all commas + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, '$1 $2'); // separate commands from commands + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, '$1 $2'); // separate commands from commands + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm, '$1 $2'); // separate commands from points + d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm, '$1 $2'); // separate commands from points + d = d.replace(/([0-9])([+\-])/gm, '$1 $2'); // separate digits when no comma + d = d.replace(/(\.[0-9]*)(\.)/gm, '$1 $2'); // separate digits when no comma + d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm, '$1 $3 $4 '); // shorthand elliptical arc path syntax + d = svg.compressSpaces(d); // compress multiple spaces + d = svg.trim(d); + this.PathParser = new (function (d) { + this.tokens = d.split(' '); + + this.reset = function () { + this.i = -1; + this.command = ''; + this.previousCommand = ''; + this.start = new svg.Point(0, 0); + this.control = new svg.Point(0, 0); + this.current = new svg.Point(0, 0); + this.points = []; + this.angles = []; + } + + this.isEnd = function () { + return this.i >= this.tokens.length - 1; + } + + this.isCommandOrEnd = function () { + if (this.isEnd()) return true; + return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null; + } + + this.isRelativeCommand = function () { + return this.command == this.command.toLowerCase(); + } + + this.getToken = function () { + this.i = this.i + 1; + return this.tokens[this.i]; + } + + this.getScalar = function () { + return parseFloat(this.getToken()); + } + + this.nextCommand = function () { + this.previousCommand = this.command; + this.command = this.getToken(); + } + + this.getPoint = function () { + var p = new svg.Point(this.getScalar(), this.getScalar()); + return this.makeAbsolute(p); + } + + this.getAsControlPoint = function () { + var p = this.getPoint(); + this.control = p; + return p; + } + + this.getAsCurrentPoint = function () { + var p = this.getPoint(); + this.current = p; + return p; + } + + this.getReflectedControlPoint = function () { + if (this.previousCommand.toLowerCase() != 'c' && this.previousCommand.toLowerCase() != 's') { + return this.current; + } + + // reflect point + var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y); + return p; + } + + this.makeAbsolute = function (p) { + if (this.isRelativeCommand()) { + p.x = this.current.x + p.x; + p.y = this.current.y + p.y; + } + return p; + } + + this.addMarker = function (p, from, priorTo) { + // if the last angle isn't filled in because we didn't have this point yet ... + if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length - 1] == null) { + this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(priorTo); + } + this.addMarkerAngle(p, from == null ? null : from.angleTo(p)); + } + + this.addMarkerAngle = function (p, a) { + this.points.push(p); + this.angles.push(a); + } + + this.getMarkerPoints = function () { + return this.points; + } + this.getMarkerAngles = function () { + for (var i = 0; i < this.angles.length; i++) { + if (this.angles[i] == null) { + for (var j = i + 1; j < this.angles.length; j++) { + if (this.angles[j] != null) { + this.angles[i] = this.angles[j]; + break; + } + } + } + } + return this.angles; + } + })(d); + + this.path = function (ctx) { + var pp = this.PathParser; + pp.reset(); + + var bb = new svg.BoundingBox(); + if (ctx != null) ctx.beginPath(); + while (!pp.isEnd()) { + pp.nextCommand(); + switch (pp.command.toUpperCase()) { + case 'M': + var p = pp.getAsCurrentPoint(); + pp.addMarker(p); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.moveTo(p.x, p.y); + pp.start = pp.current; + while (!pp.isCommandOrEnd()) { + var p = pp.getAsCurrentPoint(); + pp.addMarker(p, pp.start); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.lineTo(p.x, p.y); + } + break; + case 'L': + while (!pp.isCommandOrEnd()) { + var c = pp.current; + var p = pp.getAsCurrentPoint(); + pp.addMarker(p, c); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.lineTo(p.x, p.y); + } + break; + case 'H': + while (!pp.isCommandOrEnd()) { + var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y); + pp.addMarker(newP, pp.current); + pp.current = newP; + bb.addPoint(pp.current.x, pp.current.y); + if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y); + } + break; + case 'V': + while (!pp.isCommandOrEnd()) { + var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar()); + pp.addMarker(newP, pp.current); + pp.current = newP; + bb.addPoint(pp.current.x, pp.current.y); + if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y); + } + break; + case 'C': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var p1 = pp.getPoint(); + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl, p1); + bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + case 'S': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var p1 = pp.getReflectedControlPoint(); + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl, p1); + bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + case 'Q': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl, cntrl); + bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + case 'T': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var cntrl = pp.getReflectedControlPoint(); + pp.control = cntrl; + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl, cntrl); + bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + case 'A': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var rx = pp.getScalar(); + var ry = pp.getScalar(); + var xAxisRotation = pp.getScalar() * (Math.PI / 180.0); + var largeArcFlag = pp.getScalar(); + var sweepFlag = pp.getScalar(); + var cp = pp.getAsCurrentPoint(); + + // Conversion from endpoint to center parameterization + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + // x1', y1' + var currp = new svg.Point( + Math.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0, + -Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0 + ); + // adjust radii + var l = Math.pow(currp.x, 2) / Math.pow(rx, 2) + Math.pow(currp.y, 2) / Math.pow(ry, 2); + if (l > 1) { + rx *= Math.sqrt(l); + ry *= Math.sqrt(l); + } + // cx', cy' + var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt( + ((Math.pow(rx, 2) * Math.pow(ry, 2)) - (Math.pow(rx, 2) * Math.pow(currp.y, 2)) - (Math.pow(ry, 2) * Math.pow(currp.x, 2))) / + (Math.pow(rx, 2) * Math.pow(currp.y, 2) + Math.pow(ry, 2) * Math.pow(currp.x, 2)) + ); + if (isNaN(s)) s = 0; + var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx); + // cx, cy + var centp = new svg.Point( + (curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y, + (curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y + ); + // vector magnitude + var m = function (v) { + return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2)); + } + // ratio between two vectors + var r = function (u, v) { + return (u[0] * v[0] + u[1] * v[1]) / (m(u) * m(v)) + } + // angle between two vectors + var a = function (u, v) { + return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(r(u, v)); + } + // initial angle + var a1 = a([1, 0], [(currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry]); + // angle delta + var u = [(currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry]; + var v = [(-currp.x - cpp.x) / rx, (-currp.y - cpp.y) / ry]; + var ad = a(u, v); + if (r(u, v) <= -1) ad = Math.PI; + if (r(u, v) >= 1) ad = 0; + + if (sweepFlag == 0 && ad > 0) ad = ad - 2 * Math.PI; + if (sweepFlag == 1 && ad < 0) ad = ad + 2 * Math.PI; + + // for markers + var halfWay = new svg.Point( + centp.x - rx * Math.cos((a1 + ad) / 2), + centp.y - ry * Math.sin((a1 + ad) / 2) + ); + pp.addMarkerAngle(halfWay, (a1 + ad) / 2 + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2); + pp.addMarkerAngle(cp, ad + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2); + + bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better + if (ctx != null) { + var r = rx > ry ? rx : ry; + var sx = rx > ry ? 1 : rx / ry; + var sy = rx > ry ? ry / rx : 1; + + ctx.translate(centp.x, centp.y); + ctx.rotate(xAxisRotation); + ctx.scale(sx, sy); + ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag); + ctx.scale(1 / sx, 1 / sy); + ctx.rotate(-xAxisRotation); + ctx.translate(-centp.x, -centp.y); + } + } + break; + case 'Z': + if (ctx != null) ctx.closePath(); + pp.current = pp.start; + } + } + + return bb; + } + + this.getMarkers = function () { + var points = this.PathParser.getMarkerPoints(); + var angles = this.PathParser.getMarkerAngles(); + + var markers = []; + for (var i = 0; i < points.length; i++) { + markers.push([points[i], angles[i]]); + } + return markers; + } + } + svg.Element.path.prototype = new svg.Element.PathElementBase; + + // pattern element + svg.Element.pattern = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.createPattern = function (ctx, element) { + // render me using a temporary svg element + var tempSvg = new svg.Element.svg(); + tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value); + tempSvg.attributes['x'] = new svg.Property('x', this.attribute('x').value); + tempSvg.attributes['y'] = new svg.Property('y', this.attribute('y').value); + tempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value); + tempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value); + tempSvg.children = this.children; + + var c = document.createElement('canvas'); + c.width = this.attribute('width').Length.toPixels('x'); + c.height = this.attribute('height').Length.toPixels('y'); + tempSvg.render(c.getContext('2d')); + return ctx.createPattern(c, 'repeat'); + } + } + svg.Element.pattern.prototype = new svg.Element.ElementBase; + + // marker element + svg.Element.marker = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.baseRender = this.render; + this.render = function (ctx, point, angle) { + ctx.translate(point.x, point.y); + if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(angle); + if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(ctx.lineWidth, ctx.lineWidth); + ctx.save(); + + // render me using a temporary svg element + var tempSvg = new svg.Element.svg(); + tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value); + tempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value); + tempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value); + tempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value); + tempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value); + tempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black')); + tempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none')); + tempSvg.children = this.children; + tempSvg.render(ctx); + + ctx.restore(); + if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(1 / ctx.lineWidth, 1 / ctx.lineWidth); + if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-angle); + ctx.translate(-point.x, -point.y); + } + } + svg.Element.marker.prototype = new svg.Element.ElementBase; + + // definitions element + svg.Element.defs = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.render = function (ctx) { + // NOOP + } + } + svg.Element.defs.prototype = new svg.Element.ElementBase; + + // base for gradients + svg.Element.GradientBase = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.gradientUnits = this.attribute('gradientUnits').valueOrDefault('objectBoundingBox'); + + this.stops = []; + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + this.stops.push(child); + } + + this.getGradient = function () { + // OVERRIDE ME! + } + + this.createGradient = function (ctx, element) { + var stopsContainer = this; + if (this.attribute('xlink:href').hasValue()) { + stopsContainer = this.attribute('xlink:href').Definition.getDefinition(); + } + + var g = this.getGradient(ctx, element); + for (var i = 0; i < stopsContainer.stops.length; i++) { + g.addColorStop(stopsContainer.stops[i].offset, stopsContainer.stops[i].color); + } + + if (this.attribute('gradientTransform').hasValue()) { + // render as transformed pattern on temporary canvas + var rootView = svg.ViewPort.viewPorts[0]; + + var rect = new svg.Element.rect(); + rect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS / 3.0); + rect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS / 3.0); + rect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS); + rect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS); + + var group = new svg.Element.g(); + group.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value); + group.children = [ rect ]; + + var tempSvg = new svg.Element.svg(); + tempSvg.attributes['x'] = new svg.Property('x', 0); + tempSvg.attributes['y'] = new svg.Property('y', 0); + tempSvg.attributes['width'] = new svg.Property('width', rootView.width); + tempSvg.attributes['height'] = new svg.Property('height', rootView.height); + tempSvg.children = [ group ]; + + var c = document.createElement('canvas'); + c.width = rootView.width; + c.height = rootView.height; + var tempCtx = c.getContext('2d'); + tempCtx.fillStyle = g; + tempSvg.render(tempCtx); + return tempCtx.createPattern(c, 'no-repeat'); + } + + return g; + } + } + svg.Element.GradientBase.prototype = new svg.Element.ElementBase; + + // linear gradient element + svg.Element.linearGradient = function (node) { + this.base = svg.Element.GradientBase; + this.base(node); + + this.getGradient = function (ctx, element) { + var bb = element.getBoundingBox(); + + var x1 = (this.gradientUnits == 'objectBoundingBox' + ? bb.x() + bb.width() * this.attribute('x1').numValue() + : this.attribute('x1').Length.toPixels('x')); + var y1 = (this.gradientUnits == 'objectBoundingBox' + ? bb.y() + bb.height() * this.attribute('y1').numValue() + : this.attribute('y1').Length.toPixels('y')); + var x2 = (this.gradientUnits == 'objectBoundingBox' + ? bb.x() + bb.width() * this.attribute('x2').numValue() + : this.attribute('x2').Length.toPixels('x')); + var y2 = (this.gradientUnits == 'objectBoundingBox' + ? bb.y() + bb.height() * this.attribute('y2').numValue() + : this.attribute('y2').Length.toPixels('y')); + + return ctx.createLinearGradient(x1, y1, x2, y2); + } + } + svg.Element.linearGradient.prototype = new svg.Element.GradientBase; + + // radial gradient element + svg.Element.radialGradient = function (node) { + this.base = svg.Element.GradientBase; + this.base(node); + + this.getGradient = function (ctx, element) { + var bb = element.getBoundingBox(); + + var cx = (this.gradientUnits == 'objectBoundingBox' + ? bb.x() + bb.width() * this.attribute('cx').numValue() + : this.attribute('cx').Length.toPixels('x')); + var cy = (this.gradientUnits == 'objectBoundingBox' + ? bb.y() + bb.height() * this.attribute('cy').numValue() + : this.attribute('cy').Length.toPixels('y')); + + var fx = cx; + var fy = cy; + if (this.attribute('fx').hasValue()) { + fx = (this.gradientUnits == 'objectBoundingBox' + ? bb.x() + bb.width() * this.attribute('fx').numValue() + : this.attribute('fx').Length.toPixels('x')); + } + if (this.attribute('fy').hasValue()) { + fy = (this.gradientUnits == 'objectBoundingBox' + ? bb.y() + bb.height() * this.attribute('fy').numValue() + : this.attribute('fy').Length.toPixels('y')); + } + + var r = (this.gradientUnits == 'objectBoundingBox' + ? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue() + : this.attribute('r').Length.toPixels()); + + return ctx.createRadialGradient(fx, fy, 0, cx, cy, r); + } + } + svg.Element.radialGradient.prototype = new svg.Element.GradientBase; + + // gradient stop element + svg.Element.stop = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.offset = this.attribute('offset').numValue(); + + var stopColor = this.style('stop-color'); + if (this.style('stop-opacity').hasValue()) stopColor = stopColor.Color.addOpacity(this.style('stop-opacity').value); + this.color = stopColor.value; + } + svg.Element.stop.prototype = new svg.Element.ElementBase; + + // animation base element + svg.Element.AnimateBase = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + svg.Animations.push(this); + + this.duration = 0.0; + this.begin = this.attribute('begin').Time.toMilliseconds(); + this.maxDuration = this.begin + this.attribute('dur').Time.toMilliseconds(); + + this.getProperty = function () { + var attributeType = this.attribute('attributeType').value; + var attributeName = this.attribute('attributeName').value; + + if (attributeType == 'CSS') { + return this.parent.style(attributeName, true); + } + return this.parent.attribute(attributeName, true); + }; + + this.initialValue = null; + this.removed = false; + + this.calcValue = function () { + // OVERRIDE ME! + return ''; + } + + this.update = function (delta) { + // set initial value + if (this.initialValue == null) { + this.initialValue = this.getProperty().value; + } + + // if we're past the end time + if (this.duration > this.maxDuration) { + // loop for indefinitely repeating animations + if (this.attribute('repeatCount').value == 'indefinite') { + this.duration = 0.0 + } + else if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) { + this.removed = true; + this.getProperty().value = this.initialValue; + return true; + } + else { + return false; // no updates made + } + } + this.duration = this.duration + delta; + + // if we're past the begin time + var updated = false; + if (this.begin < this.duration) { + var newValue = this.calcValue(); // tween + + if (this.attribute('type').hasValue()) { + // for transform, etc. + var type = this.attribute('type').value; + newValue = type + '(' + newValue + ')'; + } + + this.getProperty().value = newValue; + updated = true; + } + + return updated; + } + + // fraction of duration we've covered + this.progress = function () { + return ((this.duration - this.begin) / (this.maxDuration - this.begin)); + } + } + svg.Element.AnimateBase.prototype = new svg.Element.ElementBase; + + // animate element + svg.Element.animate = function (node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function () { + var from = this.attribute('from').numValue(); + var to = this.attribute('to').numValue(); + + // tween value linearly + return from + (to - from) * this.progress(); + }; + } + svg.Element.animate.prototype = new svg.Element.AnimateBase; + + // animate color element + svg.Element.animateColor = function (node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function () { + var from = new RGBColor(this.attribute('from').value); + var to = new RGBColor(this.attribute('to').value); + + if (from.ok && to.ok) { + // tween color linearly + var r = from.r + (to.r - from.r) * this.progress(); + var g = from.g + (to.g - from.g) * this.progress(); + var b = from.b + (to.b - from.b) * this.progress(); + return 'rgb(' + parseInt(r, 10) + ',' + parseInt(g, 10) + ',' + parseInt(b, 10) + ')'; + } + return this.attribute('from').value; + }; + } + svg.Element.animateColor.prototype = new svg.Element.AnimateBase; + + // animate transform element + svg.Element.animateTransform = function (node) { + this.base = svg.Element.animate; + this.base(node); + } + svg.Element.animateTransform.prototype = new svg.Element.animate; + + // font element + svg.Element.font = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.horizAdvX = this.attribute('horiz-adv-x').numValue(); + + this.isRTL = false; + this.isArabic = false; + this.fontFace = null; + this.missingGlyph = null; + this.glyphs = []; + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + if (child.type == 'font-face') { + this.fontFace = child; + if (child.style('font-family').hasValue()) { + svg.Definitions[child.style('font-family').value] = this; + } + } + else if (child.type == 'missing-glyph') this.missingGlyph = child; + else if (child.type == 'glyph') { + if (child.arabicForm != '') { + this.isRTL = true; + this.isArabic = true; + if (typeof(this.glyphs[child.unicode]) == 'undefined') this.glyphs[child.unicode] = []; + this.glyphs[child.unicode][child.arabicForm] = child; + } + else { + this.glyphs[child.unicode] = child; + } + } + } + } + svg.Element.font.prototype = new svg.Element.ElementBase; + + // font-face element + svg.Element.fontface = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.ascent = this.attribute('ascent').value; + this.descent = this.attribute('descent').value; + this.unitsPerEm = this.attribute('units-per-em').numValue(); + } + svg.Element.fontface.prototype = new svg.Element.ElementBase; + + // missing-glyph element + svg.Element.missingglyph = function (node) { + this.base = svg.Element.path; + this.base(node); + + this.horizAdvX = 0; + } + svg.Element.missingglyph.prototype = new svg.Element.path; + + // glyph element + svg.Element.glyph = function (node) { + this.base = svg.Element.path; + this.base(node); + + this.horizAdvX = this.attribute('horiz-adv-x').numValue(); + this.unicode = this.attribute('unicode').value; + this.arabicForm = this.attribute('arabic-form').value; + } + svg.Element.glyph.prototype = new svg.Element.path; + + // text element + svg.Element.text = function (node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + if (node != null) { + // add children + this.children = []; + for (var i = 0; i < node.childNodes.length; i++) { + var childNode = node.childNodes[i]; + if (childNode.nodeType == 1) { // capture tspan and tref nodes + this.addChild(childNode, true); + } + else if (childNode.nodeType == 3) { // capture text + this.addChild(new svg.Element.tspan(childNode), false); + } + } + } + + this.baseSetContext = this.setContext; + this.setContext = function (ctx) { + this.baseSetContext(ctx); + if (this.style('dominant-baseline').hasValue()) ctx.textBaseline = this.style('dominant-baseline').value; + if (this.style('alignment-baseline').hasValue()) ctx.textBaseline = this.style('alignment-baseline').value; + } + + this.renderChildren = function (ctx) { + var textAnchor = this.style('text-anchor').valueOrDefault('start'); + var x = this.attribute('x').Length.toPixels('x'); + var y = this.attribute('y').Length.toPixels('y'); + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + + if (child.attribute('x').hasValue()) { + child.x = child.attribute('x').Length.toPixels('x'); + } + else { + if (child.attribute('dx').hasValue()) x += child.attribute('dx').Length.toPixels('x'); + child.x = x; + } + + var childLength = child.measureText(ctx); + if (textAnchor != 'start' && (i == 0 || child.attribute('x').hasValue())) { // new group? + // loop through rest of children + var groupLength = childLength; + for (var j = i + 1; j < this.children.length; j++) { + var childInGroup = this.children[j]; + if (childInGroup.attribute('x').hasValue()) break; // new group + groupLength += childInGroup.measureText(ctx); + } + child.x -= (textAnchor == 'end' ? groupLength : groupLength / 2.0); + } + x = child.x + childLength; + + if (child.attribute('y').hasValue()) { + child.y = child.attribute('y').Length.toPixels('y'); + } + else { + if (child.attribute('dy').hasValue()) y += child.attribute('dy').Length.toPixels('y'); + child.y = y; + } + y = child.y; + + child.render(ctx); + } + } + } + svg.Element.text.prototype = new svg.Element.RenderedElementBase; + + // text base + svg.Element.TextElementBase = function (node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.getGlyph = function (font, text, i) { + var c = text[i]; + var glyph = null; + if (font.isArabic) { + var arabicForm = 'isolated'; + if ((i == 0 || text[i - 1] == ' ') && i < text.length - 2 && text[i + 1] != ' ') arabicForm = 'terminal'; + if (i > 0 && text[i - 1] != ' ' && i < text.length - 2 && text[i + 1] != ' ') arabicForm = 'medial'; + if (i > 0 && text[i - 1] != ' ' && (i == text.length - 1 || text[i + 1] == ' ')) arabicForm = 'initial'; + if (typeof(font.glyphs[c]) != 'undefined') { + glyph = font.glyphs[c][arabicForm]; + if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c]; + } + } + else { + glyph = font.glyphs[c]; + } + if (glyph == null) glyph = font.missingGlyph; + return glyph; + } + + this.renderChildren = function (ctx) { + var customFont = this.parent.style('font-family').Definition.getDefinition(); + if (customFont != null) { + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); + var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle); + var text = this.getText(); + if (customFont.isRTL) text = text.split("").reverse().join(""); + + var dx = svg.ToNumberArray(this.parent.attribute('dx').value); + for (var i = 0; i < text.length; i++) { + var glyph = this.getGlyph(customFont, text, i); + var scale = fontSize / customFont.fontFace.unitsPerEm; + ctx.translate(this.x, this.y); + ctx.scale(scale, -scale); + var lw = ctx.lineWidth; + ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize; + if (fontStyle == 'italic') ctx.transform(1, 0, .4, 1, 0, 0); + glyph.render(ctx); + if (fontStyle == 'italic') ctx.transform(1, 0, -.4, 1, 0, 0); + ctx.lineWidth = lw; + ctx.scale(1 / scale, -1 / scale); + ctx.translate(-this.x, -this.y); + + this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm; + if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) { + this.x += dx[i]; + } + } + return; + } + + if (ctx.strokeStyle != '') ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y); + if (ctx.fillStyle != '') ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y); + } + + this.getText = function () { + // OVERRIDE ME + } + + this.measureText = function (ctx) { + var customFont = this.parent.style('font-family').Definition.getDefinition(); + if (customFont != null) { + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); + var measure = 0; + var text = this.getText(); + if (customFont.isRTL) text = text.split("").reverse().join(""); + var dx = svg.ToNumberArray(this.parent.attribute('dx').value); + for (var i = 0; i < text.length; i++) { + var glyph = this.getGlyph(customFont, text, i); + measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm; + if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) { + measure += dx[i]; + } + } + return measure; + } + + var textToMeasure = svg.compressSpaces(this.getText()); + if (!ctx.measureText) return textToMeasure.length * 10; + + ctx.save(); + this.setContext(ctx); + var width = ctx.measureText(textToMeasure).width; + ctx.restore(); + return width; + } + } + svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase; + + // tspan + svg.Element.tspan = function (node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.text = node.nodeType == 3 ? node.nodeValue : // text + node.childNodes.length > 0 ? node.childNodes[0].nodeValue : // element + node.text; + this.getText = function () { + return this.text; + } + } + svg.Element.tspan.prototype = new svg.Element.TextElementBase; + + // tref + svg.Element.tref = function (node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.getText = function () { + var element = this.attribute('xlink:href').Definition.getDefinition(); + if (element != null) return element.children[0].getText(); + } + } + svg.Element.tref.prototype = new svg.Element.TextElementBase; + + // a element + svg.Element.a = function (node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.hasText = true; + for (var i = 0; i < node.childNodes.length; i++) { + if (node.childNodes[i].nodeType != 3) this.hasText = false; + } + + // this might contain text + this.text = this.hasText ? node.childNodes[0].nodeValue : ''; + this.getText = function () { + return this.text; + } + + this.baseRenderChildren = this.renderChildren; + this.renderChildren = function (ctx) { + if (this.hasText) { + // render as text element + this.baseRenderChildren(ctx); + var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize); + svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.Length.toPixels('y'), this.x + this.measureText(ctx), this.y)); + } + else { + // render as temporary group + var g = new svg.Element.g(); + g.children = this.children; + g.parent = this; + g.render(ctx); + } + } + + this.onclick = function () { + window.open(this.attribute('xlink:href').value); + } + + this.onmousemove = function () { + svg.ctx.canvas.style.cursor = 'pointer'; + } + } + svg.Element.a.prototype = new svg.Element.TextElementBase; + + // image element + svg.Element.image = function (node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + svg.Images.push(this); + this.img = document.createElement('img'); + this.loaded = false; + var that = this; + this.img.onload = function () { + that.loaded = true; + } + this.img.src = this.attribute('xlink:href').value; + + this.renderChildren = function (ctx) { + var x = this.attribute('x').Length.toPixels('x'); + var y = this.attribute('y').Length.toPixels('y'); + + var width = this.attribute('width').Length.toPixels('x'); + var height = this.attribute('height').Length.toPixels('y'); + if (width == 0 || height == 0) return; + + ctx.save(); + ctx.translate(x, y); + svg.AspectRatio(ctx, + this.attribute('preserveAspectRatio').value, + width, + this.img.width, + height, + this.img.height, + 0, + 0); + ctx.drawImage(this.img, 0, 0); + ctx.restore(); + } + } + svg.Element.image.prototype = new svg.Element.RenderedElementBase; + + // group element + svg.Element.g = function (node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.getBoundingBox = function () { + var bb = new svg.BoundingBox(); + for (var i = 0; i < this.children.length; i++) { + bb.addBoundingBox(this.children[i].getBoundingBox()); + } + return bb; + }; + } + svg.Element.g.prototype = new svg.Element.RenderedElementBase; + + // symbol element + svg.Element.symbol = function (node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.baseSetContext = this.setContext; + this.setContext = function (ctx) { + this.baseSetContext(ctx); + + // viewbox + if (this.attribute('viewBox').hasValue()) { + var viewBox = svg.ToNumberArray(this.attribute('viewBox').value); + var minX = viewBox[0]; + var minY = viewBox[1]; + width = viewBox[2]; + height = viewBox[3]; + + svg.AspectRatio(ctx, + this.attribute('preserveAspectRatio').value, + this.attribute('width').Length.toPixels('x'), + width, + this.attribute('height').Length.toPixels('y'), + height, + minX, + minY); + + svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]); + } + } + } + svg.Element.symbol.prototype = new svg.Element.RenderedElementBase; + + // style element + svg.Element.style = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + // text, or spaces then CDATA + var css = node.childNodes[0].nodeValue + (node.childNodes.length > 1 ? node.childNodes[1].nodeValue : ''); + css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, ''); // remove comments + css = svg.compressSpaces(css); // replace whitespace + var cssDefs = css.split('}'); + for (var i = 0; i < cssDefs.length; i++) { + if (svg.trim(cssDefs[i]) != '') { + var cssDef = cssDefs[i].split('{'); + var cssClasses = cssDef[0].split(','); + var cssProps = cssDef[1].split(';'); + for (var j = 0; j < cssClasses.length; j++) { + var cssClass = svg.trim(cssClasses[j]); + if (cssClass != '') { + var props = {}; + for (var k = 0; k < cssProps.length; k++) { + var prop = cssProps[k].indexOf(':'); + var name = cssProps[k].substr(0, prop); + var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop); + if (name != null && value != null) { + props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value)); + } + } + svg.Styles[cssClass] = props; + if (cssClass == '@font-face') { + var fontFamily = props['font-family'].value.replace(/"/g, ''); + var srcs = props['src'].value.split(','); + for (var s = 0; s < srcs.length; s++) { + if (srcs[s].indexOf('format("svg")') > 0) { + var urlStart = srcs[s].indexOf('url'); + var urlEnd = srcs[s].indexOf(')', urlStart); + var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6); + var doc = svg.parseXml(svg.ajax(url)); + var fonts = doc.getElementsByTagName('font'); + for (var f = 0; f < fonts.length; f++) { + var font = svg.CreateElement(fonts[f]); + svg.Definitions[fontFamily] = font; + } + } + } + } + } + } + } + } + } + svg.Element.style.prototype = new svg.Element.ElementBase; + + // use element + svg.Element.use = function (node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.baseSetContext = this.setContext; + this.setContext = function (ctx) { + this.baseSetContext(ctx); + if (this.attribute('x').hasValue()) ctx.translate(this.attribute('x').Length.toPixels('x'), 0); + if (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').Length.toPixels('y')); + } + + this.getDefinition = function () { + var element = this.attribute('xlink:href').Definition.getDefinition(); + if (this.attribute('width').hasValue()) element.attribute('width', true).value = this.attribute('width').value; + if (this.attribute('height').hasValue()) element.attribute('height', true).value = this.attribute('height').value; + return element; + } + + this.path = function (ctx) { + var element = this.getDefinition(); + if (element != null) element.path(ctx); + } + + this.renderChildren = function (ctx) { + var element = this.getDefinition(); + if (element != null) element.render(ctx); + } + } + svg.Element.use.prototype = new svg.Element.RenderedElementBase; + + // mask element + svg.Element.mask = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.apply = function (ctx, element) { + // render as temp svg + var x = this.attribute('x').Length.toPixels('x'); + var y = this.attribute('y').Length.toPixels('y'); + var width = this.attribute('width').Length.toPixels('x'); + var height = this.attribute('height').Length.toPixels('y'); + + // temporarily remove mask to avoid recursion + var mask = element.attribute('mask').value; + element.attribute('mask').value = ''; + + var cMask = document.createElement('canvas'); + cMask.width = x + width; + cMask.height = y + height; + var maskCtx = cMask.getContext('2d'); + this.renderChildren(maskCtx); + + var c = document.createElement('canvas'); + c.width = x + width; + c.height = y + height; + var tempCtx = c.getContext('2d'); + element.render(tempCtx); + tempCtx.globalCompositeOperation = 'destination-in'; + tempCtx.fillStyle = maskCtx.createPattern(cMask, 'no-repeat'); + tempCtx.fillRect(0, 0, x + width, y + height); + + ctx.fillStyle = tempCtx.createPattern(c, 'no-repeat'); + ctx.fillRect(0, 0, x + width, y + height); + + // reassign mask + element.attribute('mask').value = mask; + } + + this.render = function (ctx) { + // NO RENDER + } + } + svg.Element.mask.prototype = new svg.Element.ElementBase; + + // clip element + svg.Element.clipPath = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.apply = function (ctx) { + for (var i = 0; i < this.children.length; i++) { + if (this.children[i].path) { + this.children[i].path(ctx); + ctx.clip(); + } + } + } + + this.render = function (ctx) { + // NO RENDER + } + } + svg.Element.clipPath.prototype = new svg.Element.ElementBase; + + // filters + svg.Element.filter = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.apply = function (ctx, element) { + // render as temp svg + var bb = element.getBoundingBox(); + var x = this.attribute('x').Length.toPixels('x'); + var y = this.attribute('y').Length.toPixels('y'); + if (x == 0 || y == 0) { + x = bb.x1; + y = bb.y1; + } + var width = this.attribute('width').Length.toPixels('x'); + var height = this.attribute('height').Length.toPixels('y'); + if (width == 0 || height == 0) { + width = bb.width(); + height = bb.height(); + } + + // temporarily remove filter to avoid recursion + var filter = element.style('filter').value; + element.style('filter').value = ''; + + // max filter distance + var extraPercent = .20; + var px = extraPercent * width; + var py = extraPercent * height; + + var c = document.createElement('canvas'); + c.width = width + 2 * px; + c.height = height + 2 * py; + var tempCtx = c.getContext('2d'); + tempCtx.translate(-x + px, -y + py); + element.render(tempCtx); + + // apply filters + for (var i = 0; i < this.children.length; i++) { + this.children[i].apply(tempCtx, 0, 0, width + 2 * px, height + 2 * py); + } + + // render on me + ctx.drawImage(c, 0, 0, width + 2 * px, height + 2 * py, x - px, y - py, width + 2 * px, height + 2 * py); + + // reassign filter + element.style('filter', true).value = filter; + } + + this.render = function (ctx) { + // NO RENDER + } + } + svg.Element.filter.prototype = new svg.Element.ElementBase; + + svg.Element.feGaussianBlur = function (node) { + this.base = svg.Element.ElementBase; + this.base(node); + + function make_fgauss(sigma) { + sigma = Math.max(sigma, 0.01); + var len = Math.ceil(sigma * 4.0) + 1; + mask = []; + for (var i = 0; i < len; i++) { + mask[i] = Math.exp(-0.5 * (i / sigma) * (i / sigma)); + } + return mask; + } + + function normalize(mask) { + var sum = 0; + for (var i = 1; i < mask.length; i++) { + sum += Math.abs(mask[i]); + } + sum = 2 * sum + Math.abs(mask[0]); + for (var i = 0; i < mask.length; i++) { + mask[i] /= sum; + } + return mask; + } + + function convolve_even(src, dst, mask, width, height) { + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + var a = imGet(src, x, y, width, height, 3) / 255; + for (var rgba = 0; rgba < 4; rgba++) { + var sum = mask[0] * (a == 0 ? 255 : imGet(src, x, y, width, height, rgba)) * (a == 0 || rgba == 3 ? 1 : a); + for (var i = 1; i < mask.length; i++) { + var a1 = imGet(src, Math.max(x - i, 0), y, width, height, 3) / 255; + var a2 = imGet(src, Math.min(x + i, width - 1), y, width, height, 3) / 255; + sum += mask[i] * + ((a1 == 0 ? 255 : imGet(src, Math.max(x - i, 0), y, width, height, rgba)) * (a1 == 0 || rgba == 3 ? 1 : a1) + + (a2 == 0 ? 255 : imGet(src, Math.min(x + i, width - 1), y, width, height, rgba)) * (a2 == 0 || rgba == 3 ? 1 : a2)); + } + imSet(dst, y, x, height, width, rgba, sum); + } + } + } + } + + function imGet(img, x, y, width, height, rgba) { + return img[y * width * 4 + x * 4 + rgba]; + } + + function imSet(img, x, y, width, height, rgba, val) { + img[y * width * 4 + x * 4 + rgba] = val; + } + + function blur(ctx, width, height, sigma) { + var srcData = ctx.getImageData(0, 0, width, height); + var mask = make_fgauss(sigma); + mask = normalize(mask); + tmp = []; + convolve_even(srcData.data, tmp, mask, width, height); + convolve_even(tmp, srcData.data, mask, height, width); + ctx.clearRect(0, 0, width, height); + ctx.putImageData(srcData, 0, 0); + } + + this.apply = function (ctx, x, y, width, height) { + // assuming x==0 && y==0 for now + blur(ctx, width, height, this.attribute('stdDeviation').numValue()); + } + } + svg.Element.filter.prototype = new svg.Element.feGaussianBlur; + + // title element, do nothing + svg.Element.title = function (node) { + } + svg.Element.title.prototype = new svg.Element.ElementBase; + + // desc element, do nothing + svg.Element.desc = function (node) { + } + svg.Element.desc.prototype = new svg.Element.ElementBase; + + svg.Element.MISSING = function (node) { + console.log('ERROR: Element \'' + node.nodeName + '\' not yet implemented.'); + } + svg.Element.MISSING.prototype = new svg.Element.ElementBase; + + // element factory + svg.CreateElement = function (node) { + var className = node.nodeName.replace(/^[^:]+:/, ''); // remove namespace + className = className.replace(/\-/g, ''); // remove dashes + var e = null; + if (typeof(svg.Element[className]) != 'undefined') { + e = new svg.Element[className](node); + } + else { + e = new svg.Element.MISSING(node); + } + + e.type = node.nodeName; + return e; + } + + // load from url + svg.load = function (ctx, url) { + svg.loadXml(ctx, svg.ajax(url)); + } + + // load from xml + svg.loadXml = function (ctx, xml) { + svg.loadXmlDoc(ctx, svg.parseXml(xml)); + } + + svg.loadXmlDoc = function (ctx, dom) { + svg.init(ctx); + + var mapXY = function (p) { + var e = ctx.canvas; + while (e) { + p.x -= e.offsetLeft; + p.y -= e.offsetTop; + e = e.offsetParent; + } + if (window.scrollX) p.x += window.scrollX; + if (window.scrollY) p.y += window.scrollY; + return p; + } + + // bind mouse + if (svg.opts['ignoreMouse'] != true) { + ctx.canvas.onclick = function (e) { + var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY)); + svg.Mouse.onclick(p.x, p.y); + }; + ctx.canvas.onmousemove = function (e) { + var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY)); + svg.Mouse.onmousemove(p.x, p.y); + }; + } + + var e = svg.CreateElement(dom.documentElement); + e.root = true; + + // render loop + var isFirstRender = true; + var draw = function () { + svg.ViewPort.Clear(); + if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight); + + if (svg.opts['ignoreDimensions'] != true) { + // set canvas size + if (e.style('width').hasValue()) { + ctx.canvas.width = e.style('width').Length.toPixels('x'); + ctx.canvas.style.width = ctx.canvas.width + 'px'; + } + if (e.style('height').hasValue()) { + ctx.canvas.height = e.style('height').Length.toPixels('y'); + ctx.canvas.style.height = ctx.canvas.height + 'px'; + } + } + var cWidth = ctx.canvas.clientWidth || ctx.canvas.width; + var cHeight = ctx.canvas.clientHeight || ctx.canvas.height; + svg.ViewPort.SetCurrent(cWidth, cHeight); + + if (svg.opts != null && svg.opts['offsetX'] != null) e.attribute('x', true).value = svg.opts['offsetX']; + if (svg.opts != null && svg.opts['offsetY'] != null) e.attribute('y', true).value = svg.opts['offsetY']; + if (svg.opts != null && svg.opts['scaleWidth'] != null && svg.opts['scaleHeight'] != null) { + var xRatio = 1, yRatio = 1; + if (e.attribute('width').hasValue()) xRatio = e.attribute('width').Length.toPixels('x') / svg.opts['scaleWidth']; + if (e.attribute('height').hasValue()) yRatio = e.attribute('height').Length.toPixels('y') / svg.opts['scaleHeight']; + + e.attribute('width', true).value = svg.opts['scaleWidth']; + e.attribute('height', true).value = svg.opts['scaleHeight']; + e.attribute('viewBox', true).value = '0 0 ' + (cWidth * xRatio) + ' ' + (cHeight * yRatio); + e.attribute('preserveAspectRatio', true).value = 'none'; + } + + // clear and render + if (svg.opts['ignoreClear'] != true) { + ctx.clearRect(0, 0, cWidth, cHeight); + } + e.render(ctx); + if (isFirstRender) { + isFirstRender = false; + if (svg.opts != null && typeof(svg.opts['renderCallback']) == 'function') svg.opts['renderCallback'](); + } + } + + var waitingForImages = true; + if (svg.ImagesLoaded()) { + waitingForImages = false; + draw(); + } + svg.intervalID = setInterval(function () { + var needUpdate = false; + + if (waitingForImages && svg.ImagesLoaded()) { + waitingForImages = false; + needUpdate = true; + } + + // need update from mouse events? + if (svg.opts['ignoreMouse'] != true) { + needUpdate = needUpdate | svg.Mouse.hasEvents(); + } + + // need update from animations? + if (svg.opts['ignoreAnimation'] != true) { + for (var i = 0; i < svg.Animations.length; i++) { + needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE); + } + } + + // need update from redraw? + if (svg.opts != null && typeof(svg.opts['forceRedraw']) == 'function') { + if (svg.opts['forceRedraw']() == true) needUpdate = true; + } + + // render if needed + if (needUpdate) { + draw(); + svg.Mouse.runEvents(); // run and clear our events + } + }, 1000 / svg.FRAMERATE); + } + + svg.stop = function () { + if (svg.intervalID) { + clearInterval(svg.intervalID); + } + } + + svg.Mouse = new (function () { + this.events = []; + this.hasEvents = function () { + return this.events.length != 0; + } + + this.onclick = function (x, y) { + this.events.push({ type: 'onclick', x: x, y: y, + run: function (e) { + if (e.onclick) e.onclick(); + } + }); + } + + this.onmousemove = function (x, y) { + this.events.push({ type: 'onmousemove', x: x, y: y, + run: function (e) { + if (e.onmousemove) e.onmousemove(); + } + }); + } + + this.eventElements = []; + + this.checkPath = function (element, ctx) { + for (var i = 0; i < this.events.length; i++) { + var e = this.events[i]; + if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element; + } + } + + this.checkBoundingBox = function (element, bb) { + for (var i = 0; i < this.events.length; i++) { + var e = this.events[i]; + if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element; + } + } + + this.runEvents = function () { + svg.ctx.canvas.style.cursor = ''; + + for (var i = 0; i < this.events.length; i++) { + var e = this.events[i]; + var element = this.eventElements[i]; + while (element) { + e.run(element); + element = element.parent; + } + } + + // done running, clear + this.events = []; + this.eventElements = []; + } + }); + + return svg; + } +})(); + +if (CanvasRenderingContext2D) { + CanvasRenderingContext2D.prototype.drawSvg = function (s, dx, dy, dw, dh) { + canvg(this.canvas, s, { + ignoreMouse: true, + ignoreAnimation: true, + ignoreDimensions: true, + ignoreClear: true, + offsetX: dx, + offsetY: dy, + scaleWidth: dw, + scaleHeight: dh + }); + } +} +/** + * @license Highcharts JS v2.2.5 (2012-06-08) + * CanVGRenderer Extension module + * + * (c) 2011-2012 Torstein Hønsi, Erik Olsson + * + * License: www.highcharts.com/license + */ + +// JSLint options: +/*global Highcharts */ + +(function (Highcharts) { // encapsulate + var UNDEFINED, + DIV = 'div', + ABSOLUTE = 'absolute', + RELATIVE = 'relative', + HIDDEN = 'hidden', + VISIBLE = 'visible', + PX = 'px', + css = Highcharts.css, + CanVGRenderer = Highcharts.CanVGRenderer, + SVGRenderer = Highcharts.SVGRenderer, + extend = Highcharts.extend, + merge = Highcharts.merge, + addEvent = Highcharts.addEvent, + createElement = Highcharts.createElement, + discardElement = Highcharts.discardElement; + + // Extend CanVG renderer on demand, inherit from SVGRenderer + extend(CanVGRenderer.prototype, SVGRenderer.prototype); + + // Add additional functionality: + extend(CanVGRenderer.prototype, { + create: function (chart, container, chartWidth, chartHeight) { + this.setContainer(container, chartWidth, chartHeight); + this.configure(chart); + }, + setContainer: function (container, chartWidth, chartHeight) { + var containerStyle = container.style, + containerParent = container.parentNode, + containerLeft = containerStyle.left, + containerTop = containerStyle.top, + containerOffsetWidth = container.offsetWidth, + containerOffsetHeight = container.offsetHeight, + canvas, + initialHiddenStyle = { visibility: HIDDEN, position: ABSOLUTE }; + + this.init.apply(this, [container, chartWidth, chartHeight]); + + // add the canvas above it + canvas = createElement('canvas', { + width: containerOffsetWidth, + height: containerOffsetHeight + }, { + position: RELATIVE, + left: containerLeft, + top: containerTop + }, container); + this.canvas = canvas; + + // Create the tooltip line and div, they are placed as siblings to + // the container (and as direct childs to the div specified in the html page) + this.ttLine = createElement(DIV, null, initialHiddenStyle, containerParent); + this.ttDiv = createElement(DIV, null, initialHiddenStyle, containerParent); + this.ttTimer = UNDEFINED; + + // Move away the svg node to a new div inside the container's parent so we can hide it. + var hiddenSvg = createElement(DIV, { + width: containerOffsetWidth, + height: containerOffsetHeight + }, { + visibility: HIDDEN, + left: containerLeft, + top: containerTop + }, containerParent); + this.hiddenSvg = hiddenSvg; + hiddenSvg.appendChild(this.box); + }, + + /** + * Configures the renderer with the chart. Attach a listener to the event tooltipRefresh. + **/ + configure: function (chart) { + var renderer = this, + options = chart.options.tooltip, + borderWidth = options.borderWidth, + tooltipDiv = renderer.ttDiv, + tooltipDivStyle = options.style, + tooltipLine = renderer.ttLine, + padding = parseInt(tooltipDivStyle.padding, 10); + + // Add border styling from options to the style + tooltipDivStyle = merge(tooltipDivStyle, { + padding: padding + PX, + 'background-color': options.backgroundColor, + 'border-style': 'solid', + 'border-width': borderWidth + PX, + 'border-radius': options.borderRadius + PX + }); + + // Optionally add shadow + if (options.shadow) { + tooltipDivStyle = merge(tooltipDivStyle, { + 'box-shadow': '1px 1px 3px gray', // w3c + '-webkit-box-shadow': '1px 1px 3px gray' // webkit + }); + } + css(tooltipDiv, tooltipDivStyle); + + // Set simple style on the line + css(tooltipLine, { + 'border-left': '1px solid darkgray' + }); + + // This event is triggered when a new tooltip should be shown + addEvent(chart, 'tooltipRefresh', function (args) { + var chartContainer = chart.container, + offsetLeft = chartContainer.offsetLeft, + offsetTop = chartContainer.offsetTop, + position; + + // Set the content of the tooltip + tooltipDiv.innerHTML = args.text; + + // Compute the best position for the tooltip based on the divs size and container size. + position = chart.tooltip.getPosition(tooltipDiv.offsetWidth, tooltipDiv.offsetHeight, {plotX: args.x, plotY: args.y}); + + css(tooltipDiv, { + visibility: VISIBLE, + left: position.x + PX, + top: position.y + PX, + 'border-color': args.borderColor + }); + + // Position the tooltip line + css(tooltipLine, { + visibility: VISIBLE, + left: offsetLeft + args.x + PX, + top: offsetTop + chart.plotTop + PX, + height: chart.plotHeight + PX + }); + + // This timeout hides the tooltip after 3 seconds + // First clear any existing timer + if (renderer.ttTimer !== UNDEFINED) { + clearTimeout(renderer.ttTimer); + } + + // Start a new timer that hides tooltip and line + renderer.ttTimer = setTimeout(function () { + css(tooltipDiv, { visibility: HIDDEN }); + css(tooltipLine, { visibility: HIDDEN }); + }, 3000); + }); + }, + + /** + * Extend SVGRenderer.destroy to also destroy the elements added by CanVGRenderer. + */ + destroy: function () { + var renderer = this; + + // Remove the canvas + discardElement(renderer.canvas); + + // Kill the timer + if (renderer.ttTimer !== UNDEFINED) { + clearTimeout(renderer.ttTimer); + } + + // Remove the divs for tooltip and line + discardElement(renderer.ttLine); + discardElement(renderer.ttDiv); + discardElement(renderer.hiddenSvg); + + // Continue with base class + return SVGRenderer.prototype.destroy.apply(renderer); + }, + + /** + * Take a color and return it if it's a string, do not make it a gradient even if it is a + * gradient. Currently canvg cannot render gradients (turns out black), + * see: http://code.google.com/p/canvg/issues/detail?id=104 + * + * @param {Object} color The color or config object + */ + color: function (color, elem, prop) { + if (color && color.linearGradient) { + // Pick the end color and forward to base implementation + color = color.stops[color.stops.length - 1][1]; + } + return SVGRenderer.prototype.color.call(this, color, elem, prop); + }, + + /** + * Draws the SVG on the canvas or adds a draw invokation to the deferred list. + */ + draw: function () { + var renderer = this; + window.canvg(renderer.canvas, renderer.hiddenSvg.innerHTML); + } + }); +}(Highcharts)); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/exporting.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/exporting.js new file mode 100644 index 0000000..0b406b9 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/exporting.js @@ -0,0 +1,159 @@ +/* + Highcharts JS v2.2.5 (2012-06-08) + Exporting module + + (c) 2010-2011 Torstein H?nsi + + License: www.highcharts.com/license + */ +(function () { + function x(a) { + for (var b = a.length; b--;)typeof a[b] === "number" && (a[b] = Math.round(a[b]) - 0.5); + return a + } + + var g = Highcharts, y = g.Chart, z = g.addEvent, B = g.removeEvent, r = g.createElement, u = g.discardElement, t = g.css, s = g.merge, k = g.each, n = g.extend, C = Math.max, h = document, D = window, A = h.documentElement.ontouchstart !== void 0, v = g.getOptions(); + n(v.lang, {downloadPNG: "Download PNG image", downloadJPEG: "Download JPEG image", downloadPDF: "Download PDF document", downloadSVG: "Download SVG vector image", exportButtonTitle: "Export to raster or vector image", + printButtonTitle: "Print the chart"}); + v.navigation = {menuStyle: {border: "1px solid #A0A0A0", background: "#FFFFFF"}, menuItemStyle: {padding: "0 5px", background: "none", color: "#303030", fontSize: A ? "14px" : "11px"}, menuItemHoverStyle: {background: "#4572A5", color: "#FFFFFF"}, buttonOptions: {align: "right", backgroundColor: {linearGradient: [0, 0, 0, 20], stops: [ + [0.4, "#F7F7F7"], + [0.6, "#E3E3E3"] + ]}, borderColor: "#B0B0B0", borderRadius: 3, borderWidth: 1, height: 20, hoverBorderColor: "#909090", hoverSymbolFill: "#81A7CF", hoverSymbolStroke: "#4572A5", + symbolFill: "#E0E0E0", symbolStroke: "#A0A0A0", symbolX: 11.5, symbolY: 10.5, verticalAlign: "top", width: 24, y: 10}}; + v.exporting = {type: "image/png", url: "http://export.highcharts.com/", width: 800, buttons: {exportButton: {symbol: "exportIcon", x: -10, symbolFill: "#A8BF77", hoverSymbolFill: "#768F3E", _id: "exportButton", _titleKey: "exportButtonTitle", menuItems: [ + {textKey: "downloadPNG", onclick: function () { + this.exportChart() + }}, + {textKey: "downloadJPEG", onclick: function () { + this.exportChart({type: "image/jpeg"}) + }}, + {textKey: "downloadPDF", + onclick: function () { + this.exportChart({type: "application/pdf"}) + }}, + {textKey: "downloadSVG", onclick: function () { + this.exportChart({type: "image/svg+xml"}) + }} + ]}, printButton: {symbol: "printIcon", x: -36, symbolFill: "#B5C9DF", hoverSymbolFill: "#779ABF", _id: "printButton", _titleKey: "printButtonTitle", onclick: function () { + this.print() + }}}}; + n(y.prototype, {getSVG: function (a) { + var b = this, c, d, e, f = s(b.options, a); + if (!h.createElementNS)h.createElementNS = function (a, b) { + return h.createElement(b) + }; + a = r("div", null, {position: "absolute", + top: "-9999em", width: b.chartWidth + "px", height: b.chartHeight + "px"}, h.body); + n(f.chart, {renderTo: a, forExport: !0}); + f.exporting.enabled = !1; + f.chart.plotBackgroundImage = null; + f.series = []; + k(b.series, function (a) { + e = s(a.options, {animation: !1, showCheckbox: !1, visible: a.visible}); + if (!e.isInternal) { + if (e && e.marker && /^url\(/.test(e.marker.symbol))e.marker.symbol = "circle"; + f.series.push(e) + } + }); + c = new Highcharts.Chart(f); + k(["xAxis", "yAxis"], function (a) { + k(b[a], function (b, d) { + var e = c[a][d], f = b.getExtremes(), g = f.userMin, f = f.userMax; + (g !== void 0 || f !== void 0) && e.setExtremes(g, f, !0, !1) + }) + }); + d = c.container.innerHTML; + f = null; + c.destroy(); + u(a); + d = d.replace(/zIndex="[^"]+"/g, "").replace(/isShadow="[^"]+"/g, "").replace(/symbolName="[^"]+"/g, "").replace(/jQuery[0-9]+="[^"]+"/g, "").replace(/isTracker="[^"]+"/g, "").replace(/url\([^#]+#/g, "url(#").replace(/.*?$/, "").replace(/ /g, "\u00a0").replace(/­/g, + "\u00ad").replace(//g, 'xlink:href="$1"/>').replace(/id=([^" >]+)/g, 'id="$1"').replace(/class=([^" ]+)/g, 'class="$1"').replace(/ transform /g, " ").replace(/:(path|rect)/g, "$1").replace(/style="([^"]+)"/g, function (a) { + return a.toLowerCase() + }); + d = d.replace(/(url\(#highcharts-[0-9]+)"/g, "$1").replace(/"/g, "'"); + d.match(/ xmlns="/g).length === 2 && (d = d.replace(/xmlns="[^"]+"/, + "")); + return d + }, exportChart: function (a, b) { + var c, d = this.getSVG(s(this.options.exporting.chartOptions, b)), a = s(this.options.exporting, a); + c = r("form", {method: "post", action: a.url, enctype: "multipart/form-data"}, {display: "none"}, h.body); + k(["filename", "type", "width", "svg"], function (b) { + r("input", {type: "hidden", name: b, value: {filename: a.filename || "chart", type: a.type, width: a.width, svg: d}[b]}, null, c) + }); + c.submit(); + u(c) + }, print: function () { + var a = this, b = a.container, c = [], d = b.parentNode, e = h.body, f = e.childNodes; + if (!a.isPrinting)a.isPrinting = !0, k(f, function (a, b) { + if (a.nodeType === 1)c[b] = a.style.display, a.style.display = "none" + }), e.appendChild(b), D.print(), setTimeout(function () { + d.appendChild(b); + k(f, function (a, b) { + if (a.nodeType === 1)a.style.display = c[b] + }); + a.isPrinting = !1 + }, 1E3) + }, contextMenu: function (a, b, c, d, e, f) { + var i = this, g = i.options.navigation, h = g.menuItemStyle, o = i.chartWidth, p = i.chartHeight, q = "cache-" + a, j = i[q], l = C(e, f), m, w; + if (!j)i[q] = j = r("div", {className: "highcharts-" + a}, {position: "absolute", zIndex: 1E3, padding: l + "px"}, i.container), m = r("div", + null, n({MozBoxShadow: "3px 3px 10px #888", WebkitBoxShadow: "3px 3px 10px #888", boxShadow: "3px 3px 10px #888"}, g.menuStyle), j), w = function () { + t(j, {display: "none"}) + }, z(j, "mouseleave", w), k(b, function (a) { + if (a) { + var b = r("div", {onmouseover: function () { + t(this, g.menuItemHoverStyle) + }, onmouseout: function () { + t(this, h) + }, innerHTML: a.text || i.options.lang[a.textKey]}, n({cursor: "pointer"}, h), m); + b[A ? "ontouchstart" : "onclick"] = function () { + w(); + a.onclick.apply(i, arguments) + }; + i.exportDivElements.push(b) + } + }), i.exportDivElements.push(m, + j), i.exportMenuWidth = j.offsetWidth, i.exportMenuHeight = j.offsetHeight; + a = {display: "block"}; + c + i.exportMenuWidth > o ? a.right = o - c - e - l + "px" : a.left = c - l + "px"; + d + f + i.exportMenuHeight > p ? a.bottom = p - d - l + "px" : a.top = d + f - l + "px"; + t(j, a) + }, addButton: function (a) { + function b() { + p.attr(l); + o.attr(j) + } + + var c = this, d = c.renderer, e = s(c.options.navigation.buttonOptions, a), f = e.onclick, g = e.menuItems, h = e.width, k = e.height, o, p, q, a = e.borderWidth, j = {stroke: e.borderColor}, l = {stroke: e.symbolStroke, fill: e.symbolFill}, m = e.symbolSize || 12; + if (!c.exportDivElements)c.exportDivElements = + [], c.exportSVGElements = []; + e.enabled !== !1 && (o = d.rect(0, 0, h, k, e.borderRadius, a).align(e, !0).attr(n({fill: e.backgroundColor, "stroke-width": a, zIndex: 19}, j)).add(), q = d.rect(0, 0, h, k, 0).align(e).attr({id: e._id, fill: "rgba(255, 255, 255, 0.001)", title: c.options.lang[e._titleKey], zIndex: 21}).css({cursor: "pointer"}).on("mouseover",function () { + p.attr({stroke: e.hoverSymbolStroke, fill: e.hoverSymbolFill}); + o.attr({stroke: e.hoverBorderColor}) + }).on("mouseout", b).on("click", b).add(), g && (f = function () { + b(); + var a = q.getBBox(); + c.contextMenu("export-menu", g, a.x, a.y, h, k) + }), q.on("click", function () { + f.apply(c, arguments) + }), p = d.symbol(e.symbol, e.symbolX - m / 2, e.symbolY - m / 2, m, m).align(e, !0).attr(n(l, {"stroke-width": e.symbolStrokeWidth || 1, zIndex: 20})).add(), c.exportSVGElements.push(o, q, p)) + }, destroyExport: function () { + var a, b; + for (a = 0; a < this.exportSVGElements.length; a++)b = this.exportSVGElements[a], b.onclick = b.ontouchstart = null, this.exportSVGElements[a] = b.destroy(); + for (a = 0; a < this.exportDivElements.length; a++)b = this.exportDivElements[a], + B(b, "mouseleave"), this.exportDivElements[a] = b.onmouseout = b.onmouseover = b.ontouchstart = b.onclick = null, u(b) + }}); + g.Renderer.prototype.symbols.exportIcon = function (a, b, c, d) { + return x(["M", a, b + c, "L", a + c, b + d, a + c, b + d * 0.8, a, b + d * 0.8, "Z", "M", a + c * 0.5, b + d * 0.8, "L", a + c * 0.8, b + d * 0.4, a + c * 0.4, b + d * 0.4, a + c * 0.4, b, a + c * 0.6, b, a + c * 0.6, b + d * 0.4, a + c * 0.2, b + d * 0.4, "Z"]) + }; + g.Renderer.prototype.symbols.printIcon = function (a, b, c, d) { + return x(["M", a, b + d * 0.7, "L", a + c, b + d * 0.7, a + c, b + d * 0.4, a, b + d * 0.4, "Z", "M", a + c * 0.2, b + d * 0.4, "L", a + c * 0.2, b, a + c * + 0.8, b, a + c * 0.8, b + d * 0.4, "Z", "M", a + c * 0.2, b + d * 0.7, "L", a, b + d, a + c, b + d, a + c * 0.8, b + d * 0.7, "Z"]) + }; + y.prototype.callbacks.push(function (a) { + var b, c = a.options.exporting, d = c.buttons; + if (c.enabled !== !1) { + for (b in d)a.addButton(d[b]); + z(a, "destroy", a.destroyExport) + } + }) +})(); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/exporting.src.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/exporting.src.js new file mode 100644 index 0000000..e32bf21 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/modules/exporting.src.js @@ -0,0 +1,739 @@ +/** + * @license Highcharts JS v2.2.5 (2012-06-08) + * Exporting module + * + * (c) 2010-2011 Torstein Hønsi + * + * License: www.highcharts.com/license + */ + +// JSLint options: +/*global Highcharts, document, window, Math, setTimeout */ + +(function () { // encapsulate + +// create shortcuts + var HC = Highcharts, + Chart = HC.Chart, + addEvent = HC.addEvent, + removeEvent = HC.removeEvent, + createElement = HC.createElement, + discardElement = HC.discardElement, + css = HC.css, + merge = HC.merge, + each = HC.each, + extend = HC.extend, + math = Math, + mathMax = math.max, + doc = document, + win = window, + hasTouch = doc.documentElement.ontouchstart !== undefined, + M = 'M', + L = 'L', + DIV = 'div', + HIDDEN = 'hidden', + NONE = 'none', + PREFIX = 'highcharts-', + ABSOLUTE = 'absolute', + PX = 'px', + UNDEFINED, + defaultOptions = HC.getOptions(); + + // Add language + extend(defaultOptions.lang, { + downloadPNG: 'Download PNG image', + downloadJPEG: 'Download JPEG image', + downloadPDF: 'Download PDF document', + downloadSVG: 'Download SVG vector image', + exportButtonTitle: 'Export to raster or vector image', + printButtonTitle: 'Print the chart' + }); + +// Buttons and menus are collected in a separate config option set called 'navigation'. +// This can be extended later to add control buttons like zoom and pan right click menus. + defaultOptions.navigation = { + menuStyle: { + border: '1px solid #A0A0A0', + background: '#FFFFFF' + }, + menuItemStyle: { + padding: '0 5px', + background: NONE, + color: '#303030', + fontSize: hasTouch ? '14px' : '11px' + }, + menuItemHoverStyle: { + background: '#4572A5', + color: '#FFFFFF' + }, + + buttonOptions: { + align: 'right', + backgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#F7F7F7'], + [0.6, '#E3E3E3'] + ] + }, + borderColor: '#B0B0B0', + borderRadius: 3, + borderWidth: 1, + //enabled: true, + height: 20, + hoverBorderColor: '#909090', + hoverSymbolFill: '#81A7CF', + hoverSymbolStroke: '#4572A5', + symbolFill: '#E0E0E0', + //symbolSize: 12, + symbolStroke: '#A0A0A0', + //symbolStrokeWidth: 1, + symbolX: 11.5, + symbolY: 10.5, + verticalAlign: 'top', + width: 24, + y: 10 + } + }; + + +// Add the export related options + defaultOptions.exporting = { + //enabled: true, + //filename: 'chart', + type: 'image/png', + url: 'http://export.highcharts.com/', + width: 800, + buttons: { + exportButton: { + //enabled: true, + symbol: 'exportIcon', + x: -10, + symbolFill: '#A8BF77', + hoverSymbolFill: '#768F3E', + _id: 'exportButton', + _titleKey: 'exportButtonTitle', + menuItems: [ + { + textKey: 'downloadPNG', + onclick: function () { + this.exportChart(); + } + }, + { + textKey: 'downloadJPEG', + onclick: function () { + this.exportChart({ + type: 'image/jpeg' + }); + } + }, + { + textKey: 'downloadPDF', + onclick: function () { + this.exportChart({ + type: 'application/pdf' + }); + } + }, + { + textKey: 'downloadSVG', + onclick: function () { + this.exportChart({ + type: 'image/svg+xml' + }); + } + } + // Enable this block to add "View SVG" to the dropdown menu + /* + ,{ + + text: 'View SVG', + onclick: function () { + var svg = this.getSVG() + .replace(//g, '>'); + + doc.body.innerHTML = '
        ' + svg + '
        '; + } + } // */ + ] + + }, + printButton: { + //enabled: true, + symbol: 'printIcon', + x: -36, + symbolFill: '#B5C9DF', + hoverSymbolFill: '#779ABF', + _id: 'printButton', + _titleKey: 'printButtonTitle', + onclick: function () { + this.print(); + } + } + } + }; + + + extend(Chart.prototype, { + /** + * Return an SVG representation of the chart + * + * @param additionalOptions {Object} Additional chart options for the generated SVG representation + */ + getSVG: function (additionalOptions) { + var chart = this, + chartCopy, + sandbox, + svg, + seriesOptions, + options = merge(chart.options, additionalOptions); // copy the options and add extra options + + // IE compatibility hack for generating SVG content that it doesn't really understand + if (!doc.createElementNS) { + /*jslint unparam: true*/ + /* allow unused parameter ns in function below */ + doc.createElementNS = function (ns, tagName) { + return doc.createElement(tagName); + }; + /*jslint unparam: false*/ + } + + // create a sandbox where a new chart will be generated + sandbox = createElement(DIV, null, { + position: ABSOLUTE, + top: '-9999em', + width: chart.chartWidth + PX, + height: chart.chartHeight + PX + }, doc.body); + + // override some options + extend(options.chart, { + renderTo: sandbox, + forExport: true + }); + options.exporting.enabled = false; // hide buttons in print + options.chart.plotBackgroundImage = null; // the converter doesn't handle images + + // prepare for replicating the chart + options.series = []; + each(chart.series, function (serie) { + seriesOptions = merge(serie.options, { + animation: false, // turn off animation + showCheckbox: false, + visible: serie.visible + }); + + if (!seriesOptions.isInternal) { // used for the navigator series that has its own option set + + // remove image markers + if (seriesOptions && seriesOptions.marker && /^url\(/.test(seriesOptions.marker.symbol)) { + seriesOptions.marker.symbol = 'circle'; + } + + options.series.push(seriesOptions); + } + }); + + // generate the chart copy + chartCopy = new Highcharts.Chart(options); + + // reflect axis extremes in the export + each(['xAxis', 'yAxis'], function (axisType) { + each(chart[axisType], function (axis, i) { + var axisCopy = chartCopy[axisType][i], + extremes = axis.getExtremes(), + userMin = extremes.userMin, + userMax = extremes.userMax; + + if (userMin !== UNDEFINED || userMax !== UNDEFINED) { + axisCopy.setExtremes(userMin, userMax, true, false); + } + }); + }); + + // get the SVG from the container's innerHTML + svg = chartCopy.container.innerHTML; + + // free up memory + options = null; + chartCopy.destroy(); + discardElement(sandbox); + + // sanitize + svg = svg + .replace(/zIndex="[^"]+"/g, '') + .replace(/isShadow="[^"]+"/g, '') + .replace(/symbolName="[^"]+"/g, '') + .replace(/jQuery[0-9]+="[^"]+"/g, '') + .replace(/isTracker="[^"]+"/g, '') + .replace(/url\([^#]+#/g, 'url(#') + .replace(/.*?$/, '') // any HTML added to the container after the SVG (#894) + /* This fails in IE < 8 + .replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight + return s2 +'.'+ s3[0]; + })*/ + + // Replace HTML entities, issue #347 + .replace(/ /g, '\u00A0') // no-break space + .replace(/­/g, '\u00AD') // soft hyphen + + // IE specific + .replace(//g, 'xlink:href="$1"/>') + .replace(/id=([^" >]+)/g, 'id="$1"') + .replace(/class=([^" ]+)/g, 'class="$1"') + .replace(/ transform /g, ' ') + .replace(/:(path|rect)/g, '$1') + .replace(/style="([^"]+)"/g, function (s) { + return s.toLowerCase(); + }); + + // IE9 beta bugs with innerHTML. Test again with final IE9. + svg = svg.replace(/(url\(#highcharts-[0-9]+)"/g, '$1') + .replace(/"/g, "'"); + if (svg.match(/ xmlns="/g).length === 2) { + svg = svg.replace(/xmlns="[^"]+"/, ''); + } + + return svg; + }, + + /** + * Submit the SVG representation of the chart to the server + * @param {Object} options Exporting options. Possible members are url, type and width. + * @param {Object} chartOptions Additional chart options for the SVG representation of the chart + */ + exportChart: function (options, chartOptions) { + var form, + chart = this, + svg = chart.getSVG(merge(chart.options.exporting.chartOptions, chartOptions)); // docs + + // merge the options + options = merge(chart.options.exporting, options); + + // create the form + form = createElement('form', { + method: 'post', + action: options.url, + enctype: 'multipart/form-data' + }, { + display: NONE + }, doc.body); + + // add the values + each(['filename', 'type', 'width', 'svg'], function (name) { + createElement('input', { + type: HIDDEN, + name: name, + value: { + filename: options.filename || 'chart', + type: options.type, + width: options.width, + svg: svg + }[name] + }, null, form); + }); + + // submit + form.submit(); + + // clean up + discardElement(form); + }, + + /** + * Print the chart + */ + print: function () { + + var chart = this, + container = chart.container, + origDisplay = [], + origParent = container.parentNode, + body = doc.body, + childNodes = body.childNodes; + + if (chart.isPrinting) { // block the button while in printing mode + return; + } + + chart.isPrinting = true; + + // hide all body content + each(childNodes, function (node, i) { + if (node.nodeType === 1) { + origDisplay[i] = node.style.display; + node.style.display = NONE; + } + }); + + // pull out the chart + body.appendChild(container); + + // print + win.print(); + + // allow the browser to prepare before reverting + setTimeout(function () { + + // put the chart back in + origParent.appendChild(container); + + // restore all body content + each(childNodes, function (node, i) { + if (node.nodeType === 1) { + node.style.display = origDisplay[i]; + } + }); + + chart.isPrinting = false; + + }, 1000); + + }, + + /** + * Display a popup menu for choosing the export type + * + * @param {String} name An identifier for the menu + * @param {Array} items A collection with text and onclicks for the items + * @param {Number} x The x position of the opener button + * @param {Number} y The y position of the opener button + * @param {Number} width The width of the opener button + * @param {Number} height The height of the opener button + */ + contextMenu: function (name, items, x, y, width, height) { + var chart = this, + navOptions = chart.options.navigation, + menuItemStyle = navOptions.menuItemStyle, + chartWidth = chart.chartWidth, + chartHeight = chart.chartHeight, + cacheName = 'cache-' + name, + menu = chart[cacheName], + menuPadding = mathMax(width, height), // for mouse leave detection + boxShadow = '3px 3px 10px #888', + innerMenu, + hide, + menuStyle; + + // create the menu only the first time + if (!menu) { + + // create a HTML element above the SVG + chart[cacheName] = menu = createElement(DIV, { + className: PREFIX + name + }, { + position: ABSOLUTE, + zIndex: 1000, + padding: menuPadding + PX + }, chart.container); + + innerMenu = createElement(DIV, null, + extend({ + MozBoxShadow: boxShadow, + WebkitBoxShadow: boxShadow, + boxShadow: boxShadow + }, navOptions.menuStyle), menu); + + // hide on mouse out + hide = function () { + css(menu, { display: NONE }); + }; + + addEvent(menu, 'mouseleave', hide); + + + // create the items + each(items, function (item) { + if (item) { + var div = createElement(DIV, { + onmouseover: function () { + css(this, navOptions.menuItemHoverStyle); + }, + onmouseout: function () { + css(this, menuItemStyle); + }, + innerHTML: item.text || chart.options.lang[item.textKey] + }, extend({ + cursor: 'pointer' + }, menuItemStyle), innerMenu); + + div[hasTouch ? 'ontouchstart' : 'onclick'] = function () { + hide(); + item.onclick.apply(chart, arguments); + }; + + // Keep references to menu divs to be able to destroy them + chart.exportDivElements.push(div); + } + }); + + // Keep references to menu and innerMenu div to be able to destroy them + chart.exportDivElements.push(innerMenu, menu); + + chart.exportMenuWidth = menu.offsetWidth; + chart.exportMenuHeight = menu.offsetHeight; + } + + menuStyle = { display: 'block' }; + + // if outside right, right align it + if (x + chart.exportMenuWidth > chartWidth) { + menuStyle.right = (chartWidth - x - width - menuPadding) + PX; + } else { + menuStyle.left = (x - menuPadding) + PX; + } + // if outside bottom, bottom align it + if (y + height + chart.exportMenuHeight > chartHeight) { + menuStyle.bottom = (chartHeight - y - menuPadding) + PX; + } else { + menuStyle.top = (y + height - menuPadding) + PX; + } + + css(menu, menuStyle); + }, + + /** + * Add the export button to the chart + */ + addButton: function (options) { + var chart = this, + renderer = chart.renderer, + btnOptions = merge(chart.options.navigation.buttonOptions, options), + onclick = btnOptions.onclick, + menuItems = btnOptions.menuItems, + buttonWidth = btnOptions.width, + buttonHeight = btnOptions.height, + box, + symbol, + button, + borderWidth = btnOptions.borderWidth, + boxAttr = { + stroke: btnOptions.borderColor + + }, + symbolAttr = { + stroke: btnOptions.symbolStroke, + fill: btnOptions.symbolFill + }, + symbolSize = btnOptions.symbolSize || 12; + + // Keeps references to the button elements + if (!chart.exportDivElements) { + chart.exportDivElements = []; + chart.exportSVGElements = []; + } + + if (btnOptions.enabled === false) { + return; + } + + // element to capture the click + function revert() { + symbol.attr(symbolAttr); + box.attr(boxAttr); + } + + // the box border + box = renderer.rect( + 0, + 0, + buttonWidth, + buttonHeight, + btnOptions.borderRadius, + borderWidth + ) + //.translate(buttonLeft, buttonTop) // to allow gradients + .align(btnOptions, true) + .attr(extend({ + fill: btnOptions.backgroundColor, + 'stroke-width': borderWidth, + zIndex: 19 + }, boxAttr)).add(); + + // the invisible element to track the clicks + button = renderer.rect( + 0, + 0, + buttonWidth, + buttonHeight, + 0 + ) + .align(btnOptions) + .attr({ + id: btnOptions._id, + fill: 'rgba(255, 255, 255, 0.001)', + title: chart.options.lang[btnOptions._titleKey], + zIndex: 21 + }).css({ + cursor: 'pointer' + }) + .on('mouseover', function () { + symbol.attr({ + stroke: btnOptions.hoverSymbolStroke, + fill: btnOptions.hoverSymbolFill + }); + box.attr({ + stroke: btnOptions.hoverBorderColor + }); + }) + .on('mouseout', revert) + .on('click', revert) + .add(); + + // add the click event + if (menuItems) { + onclick = function () { + revert(); + var bBox = button.getBBox(); + chart.contextMenu('export-menu', menuItems, bBox.x, bBox.y, buttonWidth, buttonHeight); + }; + } + /*addEvent(button.element, 'click', function() { + onclick.apply(chart, arguments); + });*/ + button.on('click', function () { + onclick.apply(chart, arguments); + }); + + // the icon + symbol = renderer.symbol( + btnOptions.symbol, + btnOptions.symbolX - (symbolSize / 2), + btnOptions.symbolY - (symbolSize / 2), + symbolSize, + symbolSize + ) + .align(btnOptions, true) + .attr(extend(symbolAttr, { + 'stroke-width': btnOptions.symbolStrokeWidth || 1, + zIndex: 20 + })).add(); + + // Keep references to the renderer element so to be able to destroy them later. + chart.exportSVGElements.push(box, button, symbol); + }, + + /** + * Destroy the buttons. + */ + destroyExport: function () { + var i, + chart = this, + elem; + + // Destroy the extra buttons added + for (i = 0; i < chart.exportSVGElements.length; i++) { + elem = chart.exportSVGElements[i]; + // Destroy and null the svg/vml elements + elem.onclick = elem.ontouchstart = null; + chart.exportSVGElements[i] = elem.destroy(); + } + + // Destroy the divs for the menu + for (i = 0; i < chart.exportDivElements.length; i++) { + elem = chart.exportDivElements[i]; + + // Remove the event handler + removeEvent(elem, 'mouseleave'); + + // Remove inline events + chart.exportDivElements[i] = elem.onmouseout = elem.onmouseover = elem.ontouchstart = elem.onclick = null; + + // Destroy the div by moving to garbage bin + discardElement(elem); + } + } + }); + + /** + * Crisp for 1px stroke width, which is default. In the future, consider a smarter, + * global function. + */ + function crisp(arr) { + var i = arr.length; + while (i--) { + if (typeof arr[i] === 'number') { + arr[i] = Math.round(arr[i]) - 0.5; + } + } + return arr; + } + +// Create the export icon + HC.Renderer.prototype.symbols.exportIcon = function (x, y, width, height) { + return crisp([ + M, // the disk + x, y + width, + L, + x + width, y + height, + x + width, y + height * 0.8, + x, y + height * 0.8, + 'Z', + M, // the arrow + x + width * 0.5, y + height * 0.8, + L, + x + width * 0.8, y + height * 0.4, + x + width * 0.4, y + height * 0.4, + x + width * 0.4, y, + x + width * 0.6, y, + x + width * 0.6, y + height * 0.4, + x + width * 0.2, y + height * 0.4, + 'Z' + ]); + }; +// Create the print icon + HC.Renderer.prototype.symbols.printIcon = function (x, y, width, height) { + return crisp([ + M, // the printer + x, y + height * 0.7, + L, + x + width, y + height * 0.7, + x + width, y + height * 0.4, + x, y + height * 0.4, + 'Z', + M, // the upper sheet + x + width * 0.2, y + height * 0.4, + L, + x + width * 0.2, y, + x + width * 0.8, y, + x + width * 0.8, y + height * 0.4, + 'Z', + M, // the lower sheet + x + width * 0.2, y + height * 0.7, + L, + x, y + height, + x + width, y + height, + x + width * 0.8, y + height * 0.7, + 'Z' + ]); + }; + + +// Add the buttons on chart load + Chart.prototype.callbacks.push(function (chart) { + var n, + exportingOptions = chart.options.exporting, + buttons = exportingOptions.buttons; + + if (exportingOptions.enabled !== false) { + + for (n in buttons) { + chart.addButton(buttons[n]); + } + + // Destroy the export elements at chart destroy + addEvent(chart, 'destroy', chart.destroyExport); + } + + }); + + +}()); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/dark-blue.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/dark-blue.js new file mode 100644 index 0000000..3e520ca --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/dark-blue.js @@ -0,0 +1,263 @@ +/** + * Dark blue theme for Highcharts JS + * @author Torstein Hønsi + */ + +Highcharts.theme = { + colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", + "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], + chart: { + backgroundColor: { + linearGradient: [0, 0, 250, 500], + stops: [ + [0, 'rgb(48, 48, 96)'], + [1, 'rgb(0, 0, 0)'] + ] + }, + borderColor: '#000000', + borderWidth: 2, + className: 'dark-container', + plotBackgroundColor: 'rgba(255, 255, 255, .1)', + plotBorderColor: '#CCCCCC', + plotBorderWidth: 1 + }, + title: { + style: { + color: '#C0C0C0', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineColor: '#333333', + gridLineWidth: 1, + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + tickColor: '#A0A0A0', + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + + } + } + }, + yAxis: { + gridLineColor: '#333333', + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + minorTickInterval: null, + tickColor: '#A0A0A0', + tickWidth: 1, + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.75)', + style: { + color: '#F0F0F0' + } + }, + toolbar: { + itemStyle: { + color: 'silver' + } + }, + plotOptions: { + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + legend: { + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#A0A0A0' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#444' + } + }, + credits: { + style: { + color: '#666' + } + }, + labels: { + style: { + color: '#CCC' + } + }, + + navigation: { + buttonOptions: { + backgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + borderColor: '#000000', + symbolStroke: '#C0C0C0', + hoverSymbolStroke: '#FFFFFF' + } + }, + + exporting: { + buttons: { + exportButton: { + symbolFill: '#55BE3B' + }, + printButton: { + symbolFill: '#7797BE' + } + } + }, + + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + + scrollbar: { + barBackgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: [0, 0, 0, 10], + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + }, + + // special colors for some of the + legendBackgroundColor: 'rgba(0, 0, 0, 0.5)', + legendBackgroundColorSolid: 'rgb(35, 35, 70)', + dataLabelsColor: '#444', + textColor: '#C0C0C0', + maskColor: 'rgba(255,255,255,0.3)' +}; + +// Apply the theme +var highchartsOptions = Highcharts.setOptions(Highcharts.theme); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/dark-green.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/dark-green.js new file mode 100644 index 0000000..124bb79 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/dark-green.js @@ -0,0 +1,263 @@ +/** + * Dark blue theme for Highcharts JS + * @author Torstein Hønsi + */ + +Highcharts.theme = { + colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", + "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], + chart: { + backgroundColor: { + linearGradient: [0, 0, 250, 500], + stops: [ + [0, 'rgb(48, 96, 48)'], + [1, 'rgb(0, 0, 0)'] + ] + }, + borderColor: '#000000', + borderWidth: 2, + className: 'dark-container', + plotBackgroundColor: 'rgba(255, 255, 255, .1)', + plotBorderColor: '#CCCCCC', + plotBorderWidth: 1 + }, + title: { + style: { + color: '#C0C0C0', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineColor: '#333333', + gridLineWidth: 1, + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + tickColor: '#A0A0A0', + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + + } + } + }, + yAxis: { + gridLineColor: '#333333', + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + minorTickInterval: null, + tickColor: '#A0A0A0', + tickWidth: 1, + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.75)', + style: { + color: '#F0F0F0' + } + }, + toolbar: { + itemStyle: { + color: 'silver' + } + }, + plotOptions: { + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + legend: { + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#A0A0A0' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#444' + } + }, + credits: { + style: { + color: '#666' + } + }, + labels: { + style: { + color: '#CCC' + } + }, + + navigation: { + buttonOptions: { + backgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + borderColor: '#000000', + symbolStroke: '#C0C0C0', + hoverSymbolStroke: '#FFFFFF' + } + }, + + exporting: { + buttons: { + exportButton: { + symbolFill: '#55BE3B' + }, + printButton: { + symbolFill: '#7797BE' + } + } + }, + + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + + scrollbar: { + barBackgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: [0, 0, 0, 10], + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + }, + + // special colors for some of the + legendBackgroundColor: 'rgba(0, 0, 0, 0.5)', + legendBackgroundColorSolid: 'rgb(35, 35, 70)', + dataLabelsColor: '#444', + textColor: '#C0C0C0', + maskColor: 'rgba(255,255,255,0.3)' +}; + +// Apply the theme +var highchartsOptions = Highcharts.setOptions(Highcharts.theme); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/gray.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/gray.js new file mode 100644 index 0000000..e235a4d --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/gray.js @@ -0,0 +1,262 @@ +/** + * Gray theme for Highcharts JS + * @author Torstein Hønsi + */ + +Highcharts.theme = { + colors: ["#DDDF0D", "#7798BF", "#55BF3B", "#DF5353", "#aaeeee", "#ff0066", "#eeaaee", + "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], + chart: { + backgroundColor: { + linearGradient: [0, 0, 0, 400], + stops: [ + [0, 'rgb(96, 96, 96)'], + [1, 'rgb(16, 16, 16)'] + ] + }, + borderWidth: 0, + borderRadius: 15, + plotBackgroundColor: null, + plotShadow: false, + plotBorderWidth: 0 + }, + title: { + style: { + color: '#FFF', + font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' + } + }, + subtitle: { + style: { + color: '#DDD', + font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' + } + }, + xAxis: { + gridLineWidth: 0, + lineColor: '#999', + tickColor: '#999', + labels: { + style: { + color: '#999', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#AAA', + font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' + } + } + }, + yAxis: { + alternateGridColor: null, + minorTickInterval: null, + gridLineColor: 'rgba(255, 255, 255, .1)', + lineWidth: 0, + tickWidth: 0, + labels: { + style: { + color: '#999', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#AAA', + font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' + } + } + }, + legend: { + itemStyle: { + color: '#CCC' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#333' + } + }, + labels: { + style: { + color: '#CCC' + } + }, + tooltip: { + backgroundColor: { + linearGradient: [0, 0, 0, 50], + stops: [ + [0, 'rgba(96, 96, 96, .8)'], + [1, 'rgba(16, 16, 16, .8)'] + ] + }, + borderWidth: 0, + style: { + color: '#FFF' + } + }, + + + plotOptions: { + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + + toolbar: { + itemStyle: { + color: '#CCC' + } + }, + + navigation: { + buttonOptions: { + backgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + borderColor: '#000000', + symbolStroke: '#C0C0C0', + hoverSymbolStroke: '#FFFFFF' + } + }, + + exporting: { + buttons: { + exportButton: { + symbolFill: '#55BE3B' + }, + printButton: { + symbolFill: '#7797BE' + } + } + }, + + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + + scrollbar: { + barBackgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: [0, 0, 0, 20], + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: [0, 0, 0, 10], + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + }, + + // special colors for some of the demo examples + legendBackgroundColor: 'rgba(48, 48, 48, 0.8)', + legendBackgroundColorSolid: 'rgb(70, 70, 70)', + dataLabelsColor: '#444', + textColor: '#E0E0E0', + maskColor: 'rgba(255,255,255,0.3)' +}; + +// Apply the theme +var highchartsOptions = Highcharts.setOptions(Highcharts.theme); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/grid.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/grid.js new file mode 100644 index 0000000..e6d141a --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/grid.js @@ -0,0 +1,95 @@ +/** + * Grid theme for Highcharts JS + * @author Torstein Hønsi + */ + +Highcharts.theme = { + colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4'], + chart: { + backgroundColor: { + linearGradient: [0, 0, 500, 500], + stops: [ + [0, 'rgb(255, 255, 255)'], + [1, 'rgb(240, 240, 255)'] + ] + }, + borderWidth: 2, + plotBackgroundColor: 'rgba(255, 255, 255, .9)', + plotShadow: true, + plotBorderWidth: 1 + }, + title: { + style: { + color: '#000', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineWidth: 1, + lineColor: '#000', + tickColor: '#000', + labels: { + style: { + color: '#000', + font: '11px Trebuchet MS, Verdana, sans-serif' + } + }, + title: { + style: { + color: '#333', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + + } + } + }, + yAxis: { + minorTickInterval: 'auto', + lineColor: '#000', + lineWidth: 1, + tickWidth: 1, + tickColor: '#000', + labels: { + style: { + color: '#000', + font: '11px Trebuchet MS, Verdana, sans-serif' + } + }, + title: { + style: { + color: '#333', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + legend: { + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: 'black' + + }, + itemHoverStyle: { + color: '#039' + }, + itemHiddenStyle: { + color: 'gray' + } + }, + labels: { + style: { + color: '#99b' + } + } +}; + +// Apply the theme +var highchartsOptions = Highcharts.setOptions(Highcharts.theme); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/skies.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/skies.js new file mode 100644 index 0000000..cca39d1 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/highcharts/assets/js/themes/skies.js @@ -0,0 +1,89 @@ +/** + * Skies theme for Highcharts JS + * @author Torstein Hønsi + */ + +Highcharts.theme = { + colors: ["#514F78", "#42A07B", "#9B5E4A", "#72727F", "#1F949A", "#82914E", "#86777F", "#42A07B"], + chart: { + className: 'skies', + borderWidth: 0, + plotShadow: true, + plotBackgroundImage: '/demo/gfx/skies.jpg', + plotBackgroundColor: { + linearGradient: [0, 0, 250, 500], + stops: [ + [0, 'rgba(255, 255, 255, 1)'], + [1, 'rgba(255, 255, 255, 0)'] + ] + }, + plotBorderWidth: 1 + }, + title: { + style: { + color: '#3E576F', + font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' + } + }, + subtitle: { + style: { + color: '#6D869F', + font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' + } + }, + xAxis: { + gridLineWidth: 0, + lineColor: '#C0D0E0', + tickColor: '#C0D0E0', + labels: { + style: { + color: '#666', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#666', + font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' + } + } + }, + yAxis: { + alternateGridColor: 'rgba(255, 255, 255, .5)', + lineColor: '#C0D0E0', + tickColor: '#C0D0E0', + tickWidth: 1, + labels: { + style: { + color: '#666', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#666', + font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' + } + } + }, + legend: { + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#3E576F' + }, + itemHoverStyle: { + color: 'black' + }, + itemHiddenStyle: { + color: 'silver' + } + }, + labels: { + style: { + color: '#3E576F' + } + } +}; + +// Apply the theme +var highchartsOptions = Highcharts.setOptions(Highcharts.theme); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/WhHtml5Editor.php b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/WhHtml5Editor.php new file mode 100644 index 0000000..ec74658 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/WhHtml5Editor.php @@ -0,0 +1,117 @@ + + * @copyright Copyright © 2amigos.us 2013- + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @package YiiWheels.widgets.highcharts + * @uses YiiWheels.WhHtml + */ +class WhHtml5Editor extends CInputWidget +{ + /** + * Editor language + * Supports: de-DE, es-ES, fr-FR, pt-BR, sv-SE + */ + public $lang = 'en'; + + /** + * Html options that will be assigned to the text area + */ + public $htmlOptions = array(); + + /** + * Editor options that will be passed to the editor + */ + public $pluginOptions = array(); + + /** + * Editor width + */ + public $width = '100%'; + + /** + * Editor height + */ + public $height = '400px'; + + /** + * Display editor + */ + public function run() + { + + list($name, $id) = $this->resolveNameID(); + + $this->registerClientScript($id); + + $this->htmlOptions['id'] = $id; + + if (!array_key_exists('style', $this->htmlOptions)) + $this->htmlOptions['style'] = "width:{$this->width};height:{$this->height};"; + // Do we have a model? + if ($this->hasModel()) + echo CHtml::activeTextArea($this->model, $this->attribute, $this->htmlOptions); + else + echo CHtml::textArea($name, $this->value, $this->htmlOptions); + } + + /** + * Register required script files + * @param string $id + */ + public function registerClientScript($id) + { + /* publish assets dir */ + $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'assets'; + $assetsUrl = $this->getAssetsUrl($path); + + /* @var $cs CClientScript */ + $cs = Yii::app()->getClientScript(); + + $cs->registerCssFile($assetsUrl . '/css/bootstrap-wysihtml5.css'); + if (isset($this->pluginOptions['color'])) { + $cs->registerCssFile($assetsUrl . '/css/wysiwyg-color.css'); + } + + $cs->registerScriptFile($assetsUrl . '/js/wysihtml5-0.3.0.js'); + $cs->registerScriptFile($assetsUrl . '/js/bootstrap-wysihtml5.js'); + + if (in_array(@$this->pluginOptions['locale'], array('de-DE', 'es-ES', 'fr', 'fr-NL', 'pt-BR', 'sv-SE'))) { + $cs->registerScriptFile( + $assetsUrl . '/js/locale/bootstrap-wysihtml5.' . $this->pluginOptions['locale'] . '.js' + ); + } elseif (in_array($this->lang, array('de-DE', 'es-ES', 'fr', 'fr-NL', 'pt-BR', 'sv-SE'))) { + $cs->registerScriptFile($assetsUrl . '/js/locale/bootstrap-wysihtml5.' . $this->lang . '.js'); + $this->pluginOptions['locale'] = $this->lang; + } + + $this->normalizeStylesheetsProperty(); + + /* initialize plugin */ + $selector = '#' . WhHtml::getOption('id', $this->htmlOptions, $this->getId()); + + $this->getApi()->registerPlugin('wysihtml5', $selector, $this->pluginOptions); + + } + + /** + * Normalizes stylesheet property + */ + private function normalizeStylesheetsProperty() + { + if (empty($this->pluginOptions['stylesheets'])) + $this->pluginOptions['stylesheets'] = array(); + else if (is_array($this->pluginOptions['stylesheets'])) + $this->pluginOptions['stylesheets'] = array_filter($this->pluginOptions['stylesheets'], 'is_string'); + else if (is_string($this->pluginOptions['stylesheets'])) + $this->pluginOptions['stylesheets'] = array($this->pluginOptions['stylesheets']); + else + $this->pluginOptions['stylesheets'] = array(); + } +} diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/css/bootstrap-wysihtml5.css b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/css/bootstrap-wysihtml5.css new file mode 100644 index 0000000..7948ae0 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/css/bootstrap-wysihtml5.css @@ -0,0 +1,102 @@ +ul.wysihtml5-toolbar { + margin: 0; + padding: 0; + display: block; +} + +ul.wysihtml5-toolbar::after { + clear: both; + display: table; + content: ""; +} + +ul.wysihtml5-toolbar > li { + float: left; + display: list-item; + list-style: none; + margin: 0 5px 10px 0; +} + +ul.wysihtml5-toolbar a[data-wysihtml5-command=bold] { + font-weight: bold; +} + +ul.wysihtml5-toolbar a[data-wysihtml5-command=italic] { + font-style: italic; +} + +ul.wysihtml5-toolbar a[data-wysihtml5-command=underline] { + text-decoration: underline; +} + +ul.wysihtml5-toolbar a.btn.wysihtml5-command-active { + 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); + background-color: #E6E6E6; + background-color: #D9D9D9; + outline: 0; +} + +ul.wysihtml5-commands-disabled .dropdown-menu { + display: none !important; +} + +ul.wysihtml5-toolbar div.wysihtml5-colors { + display:block; + width: 50px; + height: 20px; + margin-top: 2px; + margin-left: 5px; + position: absolute; + pointer-events: none; +} + +ul.wysihtml5-toolbar a.wysihtml5-colors-title { + padding-left: 70px; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="black"] { + background: black !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="silver"] { + background: silver !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="gray"] { + background: gray !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="maroon"] { + background: maroon !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="red"] { + background: red !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="purple"] { + background: purple !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="green"] { + background: green !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="olive"] { + background: olive !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="navy"] { + background: navy !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="blue"] { + background: blue !important; +} + +ul.wysihtml5-toolbar div[data-wysihtml5-command-value="orange"] { + background: orange !important; +} \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/css/wysiwyg-color.css b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/css/wysiwyg-color.css new file mode 100644 index 0000000..fee5d9f --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/css/wysiwyg-color.css @@ -0,0 +1,71 @@ +/** + * Default stylesheet for the bootstrap-wysihtml5 editor. + * See the TbHtml5Editor widget for details. + */ +.wysiwyg-color-black { + color: black; +} + +.wysiwyg-color-silver { + color: silver; +} + +.wysiwyg-color-gray { + color: gray; +} + +.wysiwyg-color-white { + color: white; +} + +.wysiwyg-color-maroon { + color: maroon; +} + +.wysiwyg-color-red { + color: red; +} + +.wysiwyg-color-purple { + color: purple; +} + +.wysiwyg-color-fuchsia { + color: fuchsia; +} + +.wysiwyg-color-green { + color: green; +} + +.wysiwyg-color-lime { + color: lime; +} + +.wysiwyg-color-olive { + color: olive; +} + +.wysiwyg-color-yellow { + color: yellow; +} + +.wysiwyg-color-navy { + color: navy; +} + +.wysiwyg-color-blue { + color: blue; +} + +.wysiwyg-color-teal { + color: teal; +} + +.wysiwyg-color-aqua { + color: aqua; +} + +.wysiwyg-color-orange { + color: orange; +} \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/bootstrap-wysihtml5.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/bootstrap-wysihtml5.js new file mode 100644 index 0000000..f07dadd --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/bootstrap-wysihtml5.js @@ -0,0 +1,458 @@ +!function($, wysi) { + "use strict"; + + var templates = function(key, locale) { + + var tpl = { + "font-styles": + "
        ", + + "emphasis": + "
      • " + + "" + + "
      • ", + + "lists": + "
      • " + + "
        " + + "" + + "" + + "" + + "" + + "
        " + + "
      • ", + + "link": + "
      • " + + "" + + "" + + "
      • ", + + "image": + "
      • " + + "" + + "" + + "
      • ", + + "html": + "
      • " + + "
        " + + "" + + "
        " + + "
      • ", + + "color": + "" + }; + return tpl[key]; + }; + + + var Wysihtml5 = function(el, options) { + this.el = el; + this.toolbar = this.createToolbar(el, options || defaultOptions); + this.editor = this.createEditor(options); + + window.editor = this.editor; + + $('iframe.wysihtml5-sandbox').each(function(i, el){ + $(el.contentWindow).off('focus.wysihtml5').on({ + 'focus.wysihtml5' : function(){ + $('li.dropdown').removeClass('open'); + } + }); + }); + }; + + Wysihtml5.prototype = { + + constructor: Wysihtml5, + + createEditor: function(options) { + options = options || {}; + options.toolbar = this.toolbar[0]; + + var editor = new wysi.Editor(this.el[0], options); + + if(options && options.events) { + for(var eventName in options.events) { + editor.on(eventName, options.events[eventName]); + } + } + return editor; + }, + + createToolbar: function(el, options) { + var self = this; + var toolbar = $("
          ", { + 'class' : "wysihtml5-toolbar", + 'style': "display:none" + }); + var culture = options.locale || defaultOptions.locale || "en"; + for(var key in defaultOptions) { + var value = false; + + if(options[key] !== undefined) { + if(options[key] === true) { + value = true; + } + } else { + value = defaultOptions[key]; + } + + if(value === true) { + toolbar.append(templates(key, locale[culture])); + + if(key === "html") { + this.initHtml(toolbar); + } + + if(key === "link") { + this.initInsertLink(toolbar); + } + + if(key === "image") { + this.initInsertImage(toolbar); + } + } + } + + if(options.toolbar) { + for(key in options.toolbar) { + toolbar.append(options.toolbar[key]); + } + } + + toolbar.find("a[data-wysihtml5-command='formatBlock']").click(function(e) { + var target = e.target || e.srcElement; + var el = $(target); + self.toolbar.find('.current-font').text(el.html()); + }); + + toolbar.find("a[data-wysihtml5-command='foreColor']").click(function(e) { + var target = e.target || e.srcElement; + var el = $(target); + self.toolbar.find('.current-color').text(el.html()); + }); + + this.el.before(toolbar); + + return toolbar; + }, + + initHtml: function(toolbar) { + var changeViewSelector = "a[data-wysihtml5-action='change_view']"; + toolbar.find(changeViewSelector).click(function(e) { + toolbar.find('a.btn').not(changeViewSelector).toggleClass('disabled'); + }); + }, + + initInsertImage: function(toolbar) { + var self = this; + var insertImageModal = toolbar.find('.bootstrap-wysihtml5-insert-image-modal'); + var urlInput = insertImageModal.find('.bootstrap-wysihtml5-insert-image-url'); + var insertButton = insertImageModal.find('a.btn-primary'); + var initialValue = urlInput.val(); + + var insertImage = function() { + var url = urlInput.val(); + urlInput.val(initialValue); + self.editor.composer.commands.exec("insertImage", url); + }; + + urlInput.keypress(function(e) { + if(e.which == 13) { + insertImage(); + insertImageModal.modal('hide'); + } + }); + + insertButton.click(insertImage); + + insertImageModal.on('shown', function() { + urlInput.focus(); + }); + + insertImageModal.on('hide', function() { + self.editor.currentView.element.focus(); + }); + + toolbar.find('a[data-wysihtml5-command=insertImage]').click(function() { + var activeButton = $(this).hasClass("wysihtml5-command-active"); + + if (!activeButton) { + insertImageModal.modal('show'); + insertImageModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) { + e.stopPropagation(); + }); + return false; + } + else { + return true; + } + }); + }, + + initInsertLink: function(toolbar) { + var self = this; + var insertLinkModal = toolbar.find('.bootstrap-wysihtml5-insert-link-modal'); + var urlInput = insertLinkModal.find('.bootstrap-wysihtml5-insert-link-url'); + var insertButton = insertLinkModal.find('a.btn-primary'); + var initialValue = urlInput.val(); + + var insertLink = function() { + var url = urlInput.val(); + urlInput.val(initialValue); + self.editor.composer.commands.exec("createLink", { + href: url, + target: "_blank", + rel: "nofollow" + }); + }; + var pressedEnter = false; + + urlInput.keypress(function(e) { + if(e.which == 13) { + insertLink(); + insertLinkModal.modal('hide'); + } + }); + + insertButton.click(insertLink); + + insertLinkModal.on('shown', function() { + urlInput.focus(); + }); + + insertLinkModal.on('hide', function() { + self.editor.currentView.element.focus(); + }); + + toolbar.find('a[data-wysihtml5-command=createLink]').click(function() { + var activeButton = $(this).hasClass("wysihtml5-command-active"); + + if (!activeButton) { + insertLinkModal.modal('show'); + insertLinkModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) { + e.stopPropagation(); + }); + return false; + } + else { + return true; + } + }); + } + }; + + // these define our public api + var methods = { + resetDefaults: function() { + $.fn.wysihtml5.defaultOptions = $.extend(true, {}, $.fn.wysihtml5.defaultOptionsCache); + }, + bypassDefaults: function(options) { + return this.each(function () { + var $this = $(this); + $this.data('wysihtml5', new Wysihtml5($this, options)); + }); + }, + shallowExtend: function (options) { + var settings = $.extend({}, $.fn.wysihtml5.defaultOptions, options || {}); + var that = this; + return methods.bypassDefaults.apply(that, [settings]); + }, + deepExtend: function(options) { + var settings = $.extend(true, {}, $.fn.wysihtml5.defaultOptions, options || {}); + var that = this; + return methods.bypassDefaults.apply(that, [settings]); + }, + init: function(options) { + var that = this; + return methods.shallowExtend.apply(that, [options]); + } + }; + + $.fn.wysihtml5 = function ( method ) { + if ( methods[method] ) { + return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.wysihtml5' ); + } + }; + + $.fn.wysihtml5.Constructor = Wysihtml5; + + var defaultOptions = $.fn.wysihtml5.defaultOptions = { + "font-styles": true, + "color": false, + "emphasis": true, + "lists": true, + "html": false, + "link": true, + "image": true, + events: {}, + parserRules: { + classes: { + // (path_to_project/lib/css/wysiwyg-color.css) + "wysiwyg-color-silver" : 1, + "wysiwyg-color-gray" : 1, + "wysiwyg-color-white" : 1, + "wysiwyg-color-maroon" : 1, + "wysiwyg-color-red" : 1, + "wysiwyg-color-purple" : 1, + "wysiwyg-color-fuchsia" : 1, + "wysiwyg-color-green" : 1, + "wysiwyg-color-lime" : 1, + "wysiwyg-color-olive" : 1, + "wysiwyg-color-yellow" : 1, + "wysiwyg-color-navy" : 1, + "wysiwyg-color-blue" : 1, + "wysiwyg-color-teal" : 1, + "wysiwyg-color-aqua" : 1, + "wysiwyg-color-orange" : 1, + }, + tags: { + "b": {}, + "i": {}, + "br": {}, + "ol": {}, + "ul": {}, + "li": {}, + "h1": {}, + "h2": {}, + "h3": {}, + "blockquote": {}, + "u": 1, + "img": { + "check_attributes": { + "width": "numbers", + "alt": "alt", + "src": "url", + "height": "numbers" + } + }, + "a": { + set_attributes: { + target: "_blank", + rel: "nofollow" + }, + check_attributes: { + href: "url" // important to avoid XSS + } + }, + "span": 1, + "div": 1 + } + }, + stylesheets: ["./lib/css/wysiwyg-color.css"], // (path_to_project/lib/css/wysiwyg-color.css) + locale: "en" + }; + + if (typeof $.fn.wysihtml5.defaultOptionsCache === 'undefined') { + $.fn.wysihtml5.defaultOptionsCache = $.extend(true, {}, $.fn.wysihtml5.defaultOptions); + } + + var locale = $.fn.wysihtml5.locale = { + en: { + font_styles: { + normal: "Normal text", + h1: "Heading 1", + h2: "Heading 2", + h3: "Heading 3" + }, + emphasis: { + bold: "Bold", + italic: "Italic", + underline: "Underline" + }, + lists: { + unordered: "Unordered list", + ordered: "Ordered list", + outdent: "Outdent", + indent: "Indent" + }, + link: { + insert: "Insert link", + cancel: "Cancel" + }, + image: { + insert: "Insert image", + cancel: "Cancel" + }, + html: { + edit: "Edit HTML" + }, + colours: { + black: "Black", + silver: "Silver", + gray: "Grey", + maroon: "Maroon", + red: "Red", + purple: "Purple", + green: "Green", + olive: "Olive", + navy: "Navy", + blue: "Blue", + orange: "Orange" + } + } + }; + +}(window.jQuery, window.wysihtml5); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.bg-BG.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.bg-BG.js new file mode 100644 index 0000000..6b1200e --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.bg-BG.js @@ -0,0 +1,48 @@ +/** + * Bulgarian translation for bootstrap-wysihtml5 + */ +(function($){ + $.fn.wysihtml5.locale["bg-BG"] = { + font_styles: { + normal: "Ðормален текÑÑ‚", + h1: "Форматиране 1", + h2: "Форматиране 2", + h3: "Форматиране 3" + }, + emphasis: { + bold: "Болд", + italic: "Италик", + underline: "Подчертаване" + }, + lists: { + unordered: "Ðеподреден лиÑÑ‚", + ordered: "Подреден лиÑÑ‚", + outdent: "ОтÑтъпване", + indent: "ЗаÑтъпване" + }, + link: { + insert: "ПоÑтавете линк", + cancel: "Отказване" + }, + image: { + insert: "ПоÑтавете изображение", + cancel: "Отказване" + }, + html: { + edit: "Ð ÐµÐ´Ð°ÐºÑ†Ð¸Ñ Ð½Ð° HTML" + }, + colours: { + black: "Черно", + silver: "Сребърно", + gray: "Сиво", + maroon: "КеÑтенÑво", + red: "Червено", + purple: "Пурпурно", + green: "Зелено", + olive: "МаÑлинено", + navy: "МорÑко Ñиньо", + blue: "Синьо", + orange: "Оранжево" + } + }; +}(jQuery)); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.de-DE.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.de-DE.js new file mode 100644 index 0000000..8b89bd1 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.de-DE.js @@ -0,0 +1,48 @@ +/** + * German translation for bootstrap-wysihtml5 + */ +(function($){ + $.fn.wysihtml5.locale["de-DE"] = { + font_styles: { + normal: "Normaler Text", + h1: "Überschrift 1", + h2: "Überschrift 2", + h3: "Überschrift 3" + }, + emphasis: { + bold: "Fett", + italic: "Kursiv", + underline: "Unterstrichen" + }, + lists: { + unordered: "Ungeordnete Liste", + ordered: "Geordnete Liste", + outdent: "Einzug verkleinern", + indent: "Einzug vergrößern" + }, + link: { + insert: "Link einfügen", + cancel: "Abbrechen" + }, + image: { + insert: "Bild einfügen", + cancel: "Abbrechen" + }, + html: { + edit: "HTML bearbeiten" + }, + colours: { + black: "Schwarz", + silver: "Silber", + gray: "Grau", + maroon: "Kastanienbraun", + red: "Rot", + purple: "Violett", + green: "Grün", + olive: "Olivgrün", + navy: "Marineblau", + blue: "Blau", + orange: "Orange" + } + }; +}(jQuery)); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.es-ES.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.es-ES.js new file mode 100644 index 0000000..134a219 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.es-ES.js @@ -0,0 +1,34 @@ +/** + * Uruguayan spanish translation for bootstrap-wysihtml5 + */ +(function($){ + $.fn.wysihtml5.locale["es-ES"] = { + font_styles: { + normal: "Texto normal", + h1: "Título 1", + h2: "Título 2" + }, + emphasis: { + bold: "Negrita", + italic: "Itálica", + underline: "Subrayado" + }, + lists: { + unordered: "Lista desordenada", + ordered: "Lista ordenada", + outdent: "Eliminar sangría", + indent: "Agregar sangría" + }, + link: { + insert: "Insertar link", + cancel: "Cancelar" + }, + image: { + insert: "Insertar imagen", + cancel: "Cancelar" + }, + html: { + edit: "Editar HTML" + } + }; +}(jQuery)); \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.fr-FR.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.fr-FR.js new file mode 100644 index 0000000..e6d02a0 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.fr-FR.js @@ -0,0 +1,49 @@ +/** + * French translation for bootstrap-wysihtml5 + */ +(function($){ + $.fn.wysihtml5.locale["fr-FR"] = { + font_styles: { + normal: "Texte normal", + h1: "Titre 1", + h2: "Titre 2", + h3: "Titre 3" + }, + emphasis: { + bold: "Gras", + italic: "Italique", + underline: "Souligné" + }, + lists: { + unordered: "Liste à puces", + ordered: "Liste numérotée", + outdent: "Diminuer le retrait", + indent: "Augmenter le retrait", + indered: "Augmenter le retrait" + }, + link: { + insert: "Insérer un lien", + cancel: "Annuler" + }, + image: { + insert: "Insérer une image", + cancel: "Annuler" + }, + html: { + edit: "Editer en HTML" + }, + colours: { + black: "Noir", + silver: "Gris clair", + gray: "Gris", + maroon: "Marron", + red: "Rouge", + purple: "Pourpre", + green: "Vert", + olive: "Olive", + navy: "Bleu marine", + blue: "Bleu", + orange: "Orange" + } + }; +}(jQuery)); \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.fr-NL.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.fr-NL.js new file mode 100644 index 0000000..1b0a102 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.fr-NL.js @@ -0,0 +1,48 @@ +/** + * German translation for bootstrap-wysihtml5 + */ +(function($){ + $.fn.wysihtml5.locale["nl-NL"] = { + font_styles: { + normal: "Normale tekst", + h1: "Kop 1", + h2: "Kop 2", + h3: "Kop 3" + }, + emphasis: { + bold: "Vet", + italic: "Cursief", + underline: "Onderstrepen" + }, + lists: { + unordered: "Lijst met opsommingstekens", + ordered: "Genummerde lijst", + outdent: "Inspringing verkleinen", + indent: "Inspringing vergroten" + }, + link: { + insert: "Link invoegen", + cancel: "Annuleer" + }, + image: { + insert: "Afbeelding invoegen", + cancel: "Annuleer" + }, + html: { + edit: "HTML bewerken" + }, + colours: { + black: "Zwart", + silver: "Zilver", + gray: "Grijs", + maroon: "Kastanjebruin", + red: "Root", + purple: "Paars", + green: "Groen", + olive: "Olijfgroen", + navy: "Donkerblauw", + blue: "Blauw", + orange: "Oranje" + } + }; +}(jQuery)); \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.hu-HU.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.hu-HU.js new file mode 100644 index 0000000..0f8169f --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.hu-HU.js @@ -0,0 +1,48 @@ +/** + * Hungarian translation for bootstrap-wysihtml5 + */ +(function($){ + $.fn.wysihtml5.locale["hu-HU"] = { + font_styles: { + normal: "Normál szöveg", + h1: "Fejléc 1", + h2: "Fejléc 2", + h3: "Fejléc 3" + }, + emphasis: { + bold: "Félkövér", + italic: "DÅ‘lt", + underline: "Aláhúzott" + }, + lists: { + unordered: "Rendezetlen lista", + ordered: "Rendezett lista", + outdent: "Behúzás csökkentése", + indent: "Behúzás" + }, + link: { + insert: "Link beszúrása", + cancel: "Mégsem" + }, + image: { + insert: "Kép beszúrása", + cancel: "Mégsem" + }, + html: { + edit: "HTML szerkesztése" + }, + colours: { + black: "Fekete", + silver: "Ezüst", + gray: "Szürke", + maroon: "Barna", + red: "Piros", + purple: "Lila", + green: "Zöld", + olive: "Olivazöld", + navy: "Sötétkék", + blue: "Kék", + orange: "Narancssárga" + } + }; +}(jQuery)); diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.pt-BR.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.pt-BR.js new file mode 100644 index 0000000..7070d4e --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.pt-BR.js @@ -0,0 +1,48 @@ +/** + * Brazilian portuguese translation for bootstrap-wysihtml5 + */ +(function($){ + $.fn.wysihtml5.locale["pt-BR"] = { + font_styles: { + normal: "Texto normal", + h1: "Título 1", + h2: "Título 2", + h3: "Título 3" + }, + emphasis: { + bold: "Negrito", + italic: "Itálico", + underline: "Sublinhado" + }, + lists: { + unordered: "Lista", + ordered: "Lista numerada", + outdent: "Remover indentação", + indent: "Indentar" + }, + link: { + insert: "Inserir link", + cancel: "Cancelar" + }, + image: { + insert: "Inserir imagem", + cancel: "Cancelar" + }, + html: { + edit: "Editar HTML" + }, + colours: { + black: "Preto", + silver: "Prata", + gray: "Cinza", + maroon: "Marrom", + red: "Vermelho", + purple: "Roxo", + green: "Verde", + olive: "Oliva", + navy: "Marinho", + blue: "Azul", + orange: "Laranja" + } + }; +}(jQuery)); \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.sv-SE.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.sv-SE.js new file mode 100644 index 0000000..03f8246 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/locale/bootstrap-wysihtml5.sv-SE.js @@ -0,0 +1,48 @@ +/** + * Swedish translation for bootstrap-wysihtml5 + */ +(function($){ + $.fn.wysihtml5.locale["sv-SE"] = { + font_styles: { + normal: "Normal Text", + h1: "Rubrik 1", + h2: "Rubrik 2", + h3: "Rubrik 3" + }, + emphasis: { + bold: "Fet", + italic: "Kursiv", + underline: "Understruken" + }, + lists: { + unordered: "Osorterad lista", + ordered: "Sorterad lista", + outdent: "Minska indrag", + indent: "Öka indrag" + }, + link: { + insert: "Lägg till länk", + cancel: "Avbryt" + }, + image: { + insert: "Lägg till Bild", + cancel: "Avbryt" + }, + html: { + edit: "Redigera HTML" + }, + colours: { + black: "Svart", + silver: "Silver", + gray: "GrÃ¥", + maroon: "Kastaniebrun", + red: "Röd", + purple: "Lila", + green: "Grön", + olive: "Olivgrön", + navy: "MarinblÃ¥", + blue: "BlÃ¥", + orange: "Orange" + } + }; +}(jQuery)); \ No newline at end of file diff --git a/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/wysihtml5-0.3.0.js b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/wysihtml5-0.3.0.js new file mode 100644 index 0000000..b40e9a2 --- /dev/null +++ b/src/common/lib/vendor/2amigos/yiiwheels/widgets/html5editor/assets/js/wysihtml5-0.3.0.js @@ -0,0 +1,9523 @@ +/** + * @license wysihtml5 v0.3.0 + * https://github.com/xing/wysihtml5 + * + * Author: Christopher Blum (https://github.com/tiff) + * + * Copyright (C) 2012 XING AG + * Licensed under the MIT license (MIT) + * + */ +var wysihtml5 = { + version: "0.3.0", + + // namespaces + commands: {}, + dom: {}, + quirks: {}, + toolbar: {}, + lang: {}, + selection: {}, + views: {}, + + INVISIBLE_SPACE: "\uFEFF", + + EMPTY_FUNCTION: function() {}, + + ELEMENT_NODE: 1, + TEXT_NODE: 3, + + BACKSPACE_KEY: 8, + ENTER_KEY: 13, + ESCAPE_KEY: 27, + SPACE_KEY: 32, + DELETE_KEY: 46 +};/** + * @license Rangy, a cross-browser JavaScript range and selection library + * http://code.google.com/p/rangy/ + * + * Copyright 2011, Tim Down + * Licensed under the MIT license. + * Version: 1.2.2 + * Build date: 13 November 2011 + */ +window['rangy'] = (function() { + + + var OBJECT = "object", FUNCTION = "function", UNDEFINED = "undefined"; + + var domRangeProperties = ["startContainer", "startOffset", "endContainer", "endOffset", "collapsed", + "commonAncestorContainer", "START_TO_START", "START_TO_END", "END_TO_START", "END_TO_END"]; + + var domRangeMethods = ["setStart", "setStartBefore", "setStartAfter", "setEnd", "setEndBefore", + "setEndAfter", "collapse", "selectNode", "selectNodeContents", "compareBoundaryPoints", "deleteContents", + "extractContents", "cloneContents", "insertNode", "surroundContents", "cloneRange", "toString", "detach"]; + + var textRangeProperties = ["boundingHeight", "boundingLeft", "boundingTop", "boundingWidth", "htmlText", "text"]; + + // Subset of TextRange's full set of methods that we're interested in + var textRangeMethods = ["collapse", "compareEndPoints", "duplicate", "getBookmark", "moveToBookmark", + "moveToElementText", "parentElement", "pasteHTML", "select", "setEndPoint", "getBoundingClientRect"]; + + /*----------------------------------------------------------------------------------------------------------------*/ + + // Trio of functions taken from Peter Michaux's article: + // http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting + function isHostMethod(o, p) { + var t = typeof o[p]; + return t == FUNCTION || (!!(t == OBJECT && o[p])) || t == "unknown"; + } + + function isHostObject(o, p) { + return !!(typeof o[p] == OBJECT && o[p]); + } + + function isHostProperty(o, p) { + return typeof o[p] != UNDEFINED; + } + + // Creates a convenience function to save verbose repeated calls to tests functions + function createMultiplePropertyTest(testFunc) { + return function(o, props) { + var i = props.length; + while (i--) { + if (!testFunc(o, props[i])) { + return false; + } + } + return true; + }; + } + + // Next trio of functions are a convenience to save verbose repeated calls to previous two functions + var areHostMethods = createMultiplePropertyTest(isHostMethod); + var areHostObjects = createMultiplePropertyTest(isHostObject); + var areHostProperties = createMultiplePropertyTest(isHostProperty); + + function isTextRange(range) { + return range && areHostMethods(range, textRangeMethods) && areHostProperties(range, textRangeProperties); + } + + var api = { + version: "1.2.2", + initialized: false, + supported: true, + + util: { + isHostMethod: isHostMethod, + isHostObject: isHostObject, + isHostProperty: isHostProperty, + areHostMethods: areHostMethods, + areHostObjects: areHostObjects, + areHostProperties: areHostProperties, + isTextRange: isTextRange + }, + + features: {}, + + modules: {}, + config: { + alertOnWarn: false, + preferTextRange: false + } + }; + + function fail(reason) { + window.alert("Rangy not supported in your browser. Reason: " + reason); + api.initialized = true; + api.supported = false; + } + + api.fail = fail; + + function warn(msg) { + var warningMessage = "Rangy warning: " + msg; + if (api.config.alertOnWarn) { + window.alert(warningMessage); + } else if (typeof window.console != UNDEFINED && typeof window.console.log != UNDEFINED) { + window.console.log(warningMessage); + } + } + + api.warn = warn; + + if ({}.hasOwnProperty) { + api.util.extend = function(o, props) { + for (var i in props) { + if (props.hasOwnProperty(i)) { + o[i] = props[i]; + } + } + }; + } else { + fail("hasOwnProperty not supported"); + } + + var initListeners = []; + var moduleInitializers = []; + + // Initialization + function init() { + if (api.initialized) { + return; + } + var testRange; + var implementsDomRange = false, implementsTextRange = false; + + // First, perform basic feature tests + + if (isHostMethod(document, "createRange")) { + testRange = document.createRange(); + if (areHostMethods(testRange, domRangeMethods) && areHostProperties(testRange, domRangeProperties)) { + implementsDomRange = true; + } + testRange.detach(); + } + + var body = isHostObject(document, "body") ? document.body : document.getElementsByTagName("body")[0]; + + if (body && isHostMethod(body, "createTextRange")) { + testRange = body.createTextRange(); + if (isTextRange(testRange)) { + implementsTextRange = true; + } + } + + if (!implementsDomRange && !implementsTextRange) { + fail("Neither Range nor TextRange are implemented"); + } + + api.initialized = true; + api.features = { + implementsDomRange: implementsDomRange, + implementsTextRange: implementsTextRange + }; + + // Initialize modules and call init listeners + var allListeners = moduleInitializers.concat(initListeners); + for (var i = 0, len = allListeners.length; i < len; ++i) { + try { + allListeners[i](api); + } catch (ex) { + if (isHostObject(window, "console") && isHostMethod(window.console, "log")) { + window.console.log("Init listener threw an exception. Continuing.", ex); + } + + } + } + } + + // Allow external scripts to initialize this library in case it's loaded after the document has loaded + api.init = init; + + // Execute listener immediately if already initialized + api.addInitListener = function(listener) { + if (api.initialized) { + listener(api); + } else { + initListeners.push(listener); + } + }; + + var createMissingNativeApiListeners = []; + + api.addCreateMissingNativeApiListener = function(listener) { + createMissingNativeApiListeners.push(listener); + }; + + function createMissingNativeApi(win) { + win = win || window; + init(); + + // Notify listeners + for (var i = 0, len = createMissingNativeApiListeners.length; i < len; ++i) { + createMissingNativeApiListeners[i](win); + } + } + + api.createMissingNativeApi = createMissingNativeApi; + + /** + * @constructor + */ + function Module(name) { + this.name = name; + this.initialized = false; + this.supported = false; + } + + Module.prototype.fail = function(reason) { + this.initialized = true; + this.supported = false; + + throw new Error("Module '" + this.name + "' failed to load: " + reason); + }; + + Module.prototype.warn = function(msg) { + api.warn("Module " + this.name + ": " + msg); + }; + + Module.prototype.createError = function(msg) { + return new Error("Error in Rangy " + this.name + " module: " + msg); + }; + + api.createModule = function(name, initFunc) { + var module = new Module(name); + api.modules[name] = module; + + moduleInitializers.push(function(api) { + initFunc(api, module); + module.initialized = true; + module.supported = true; + }); + }; + + api.requireModules = function(modules) { + for (var i = 0, len = modules.length, module, moduleName; i < len; ++i) { + moduleName = modules[i]; + module = api.modules[moduleName]; + if (!module || !(module instanceof Module)) { + throw new Error("Module '" + moduleName + "' not found"); + } + if (!module.supported) { + throw new Error("Module '" + moduleName + "' not supported"); + } + } + }; + + /*----------------------------------------------------------------------------------------------------------------*/ + + // Wait for document to load before running tests + + var docReady = false; + + var loadHandler = function(e) { + + if (!docReady) { + docReady = true; + if (!api.initialized) { + init(); + } + } + }; + + // Test whether we have window and document objects that we will need + if (typeof window == UNDEFINED) { + fail("No window found"); + return; + } + if (typeof document == UNDEFINED) { + fail("No document found"); + return; + } + + if (isHostMethod(document, "addEventListener")) { + document.addEventListener("DOMContentLoaded", loadHandler, false); + } + + // Add a fallback in case the DOMContentLoaded event isn't supported + if (isHostMethod(window, "addEventListener")) { + window.addEventListener("load", loadHandler, false); + } else if (isHostMethod(window, "attachEvent")) { + window.attachEvent("onload", loadHandler); + } else { + fail("Window does not have required addEventListener or attachEvent method"); + } + + return api; +})(); +rangy.createModule("DomUtil", function(api, module) { + + var UNDEF = "undefined"; + var util = api.util; + + // Perform feature tests + if (!util.areHostMethods(document, ["createDocumentFragment", "createElement", "createTextNode"])) { + module.fail("document missing a Node creation method"); + } + + if (!util.isHostMethod(document, "getElementsByTagName")) { + module.fail("document missing getElementsByTagName method"); + } + + var el = document.createElement("div"); + if (!util.areHostMethods(el, ["insertBefore", "appendChild", "cloneNode"] || + !util.areHostObjects(el, ["previousSibling", "nextSibling", "childNodes", "parentNode"]))) { + module.fail("Incomplete Element implementation"); + } + + // innerHTML is required for Range's createContextualFragment method + if (!util.isHostProperty(el, "innerHTML")) { + module.fail("Element is missing innerHTML property"); + } + + var textNode = document.createTextNode("test"); + if (!util.areHostMethods(textNode, ["splitText", "deleteData", "insertData", "appendData", "cloneNode"] || + !util.areHostObjects(el, ["previousSibling", "nextSibling", "childNodes", "parentNode"]) || + !util.areHostProperties(textNode, ["data"]))) { + module.fail("Incomplete Text Node implementation"); + } + + /*----------------------------------------------------------------------------------------------------------------*/ + + // Removed use of indexOf because of a bizarre bug in Opera that is thrown in one of the Acid3 tests. I haven't been + // able to replicate it outside of the test. The bug is that indexOf returns -1 when called on an Array that + // contains just the document as a single element and the value searched for is the document. + var arrayContains = /*Array.prototype.indexOf ? + function(arr, val) { + return arr.indexOf(val) > -1; + }:*/ + + function(arr, val) { + var i = arr.length; + while (i--) { + if (arr[i] === val) { + return true; + } + } + return false; + }; + + // Opera 11 puts HTML elements in the null namespace, it seems, and IE 7 has undefined namespaceURI + function isHtmlNamespace(node) { + var ns; + return typeof node.namespaceURI == UNDEF || ((ns = node.namespaceURI) === null || ns == "http://www.w3.org/1999/xhtml"); + } + + function parentElement(node) { + var parent = node.parentNode; + return (parent.nodeType == 1) ? parent : null; + } + + function getNodeIndex(node) { + var i = 0; + while( (node = node.previousSibling) ) { + i++; + } + return i; + } + + function getNodeLength(node) { + var childNodes; + return isCharacterDataNode(node) ? node.length : ((childNodes = node.childNodes) ? childNodes.length : 0); + } + + function getCommonAncestor(node1, node2) { + var ancestors = [], n; + for (n = node1; n; n = n.parentNode) { + ancestors.push(n); + } + + for (n = node2; n; n = n.parentNode) { + if (arrayContains(ancestors, n)) { + return n; + } + } + + return null; + } + + function isAncestorOf(ancestor, descendant, selfIsAncestor) { + var n = selfIsAncestor ? descendant : descendant.parentNode; + while (n) { + if (n === ancestor) { + return true; + } else { + n = n.parentNode; + } + } + return false; + } + + function getClosestAncestorIn(node, ancestor, selfIsAncestor) { + var p, n = selfIsAncestor ? node : node.parentNode; + while (n) { + p = n.parentNode; + if (p === ancestor) { + return n; + } + n = p; + } + return null; + } + + function isCharacterDataNode(node) { + var t = node.nodeType; + return t == 3 || t == 4 || t == 8 ; // Text, CDataSection or Comment + } + + function insertAfter(node, precedingNode) { + var nextNode = precedingNode.nextSibling, parent = precedingNode.parentNode; + if (nextNode) { + parent.insertBefore(node, nextNode); + } else { + parent.appendChild(node); + } + return node; + } + + // Note that we cannot use splitText() because it is bugridden in IE 9. + function splitDataNode(node, index) { + var newNode = node.cloneNode(false); + newNode.deleteData(0, index); + node.deleteData(index, node.length - index); + insertAfter(newNode, node); + return newNode; + } + + function getDocument(node) { + if (node.nodeType == 9) { + return node; + } else if (typeof node.ownerDocument != UNDEF) { + return node.ownerDocument; + } else if (typeof node.document != UNDEF) { + return node.document; + } else if (node.parentNode) { + return getDocument(node.parentNode); + } else { + throw new Error("getDocument: no document found for node"); + } + } + + function getWindow(node) { + var doc = getDocument(node); + if (typeof doc.defaultView != UNDEF) { + return doc.defaultView; + } else if (typeof doc.parentWindow != UNDEF) { + return doc.parentWindow; + } else { + throw new Error("Cannot get a window object for node"); + } + } + + function getIframeDocument(iframeEl) { + if (typeof iframeEl.contentDocument != UNDEF) { + return iframeEl.contentDocument; + } else if (typeof iframeEl.contentWindow != UNDEF) { + return iframeEl.contentWindow.document; + } else { + throw new Error("getIframeWindow: No Document object found for iframe element"); + } + } + + function getIframeWindow(iframeEl) { + if (typeof iframeEl.contentWindow != UNDEF) { + return iframeEl.contentWindow; + } else if (typeof iframeEl.contentDocument != UNDEF) { + return iframeEl.contentDocument.defaultView; + } else { + throw new Error("getIframeWindow: No Window object found for iframe element"); + } + } + + function getBody(doc) { + return util.isHostObject(doc, "body") ? doc.body : doc.getElementsByTagName("body")[0]; + } + + function getRootContainer(node) { + var parent; + while ( (parent = node.parentNode) ) { + node = parent; + } + return node; + } + + function comparePoints(nodeA, offsetA, nodeB, offsetB) { + // See http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Comparing + var nodeC, root, childA, childB, n; + if (nodeA == nodeB) { + + // Case 1: nodes are the same + return offsetA === offsetB ? 0 : (offsetA < offsetB) ? -1 : 1; + } else if ( (nodeC = getClosestAncestorIn(nodeB, nodeA, true)) ) { + + // Case 2: node C (container B or an ancestor) is a child node of A + return offsetA <= getNodeIndex(nodeC) ? -1 : 1; + } else if ( (nodeC = getClosestAncestorIn(nodeA, nodeB, true)) ) { + + // Case 3: node C (container A or an ancestor) is a child node of B + return getNodeIndex(nodeC) < offsetB ? -1 : 1; + } else { + + // Case 4: containers are siblings or descendants of siblings + root = getCommonAncestor(nodeA, nodeB); + childA = (nodeA === root) ? root : getClosestAncestorIn(nodeA, root, true); + childB = (nodeB === root) ? root : getClosestAncestorIn(nodeB, root, true); + + if (childA === childB) { + // This shouldn't be possible + + throw new Error("comparePoints got to case 4 and childA and childB are the same!"); + } else { + n = root.firstChild; + while (n) { + if (n === childA) { + return -1; + } else if (n === childB) { + return 1; + } + n = n.nextSibling; + } + throw new Error("Should not be here!"); + } + } + } + + function fragmentFromNodeChildren(node) { + var fragment = getDocument(node).createDocumentFragment(), child; + while ( (child = node.firstChild) ) { + fragment.appendChild(child); + } + return fragment; + } + + function inspectNode(node) { + if (!node) { + return "[No node]"; + } + if (isCharacterDataNode(node)) { + return '"' + node.data + '"'; + } else if (node.nodeType == 1) { + var idAttr = node.id ? ' id="' + node.id + '"' : ""; + return "<" + node.nodeName + idAttr + ">[" + node.childNodes.length + "]"; + } else { + return node.nodeName; + } + } + + /** + * @constructor + */ + function NodeIterator(root) { + this.root = root; + this._next = root; + } + + NodeIterator.prototype = { + _current: null, + + hasNext: function() { + return !!this._next; + }, + + next: function() { + var n = this._current = this._next; + var child, next; + if (this._current) { + child = n.firstChild; + if (child) { + this._next = child; + } else { + next = null; + while ((n !== this.root) && !(next = n.nextSibling)) { + n = n.parentNode; + } + this._next = next; + } + } + return this._current; + }, + + detach: function() { + this._current = this._next = this.root = null; + } + }; + + function createIterator(root) { + return new NodeIterator(root); + } + + /** + * @constructor + */ + function DomPosition(node, offset) { + this.node = node; + this.offset = offset; + } + + DomPosition.prototype = { + equals: function(pos) { + return this.node === pos.node & this.offset == pos.offset; + }, + + inspect: function() { + return "[DomPosition(" + inspectNode(this.node) + ":" + this.offset + ")]"; + } + }; + + /** + * @constructor + */ + function DOMException(codeName) { + this.code = this[codeName]; + this.codeName = codeName; + this.message = "DOMException: " + this.codeName; + } + + DOMException.prototype = { + INDEX_SIZE_ERR: 1, + HIERARCHY_REQUEST_ERR: 3, + WRONG_DOCUMENT_ERR: 4, + NO_MODIFICATION_ALLOWED_ERR: 7, + NOT_FOUND_ERR: 8, + NOT_SUPPORTED_ERR: 9, + INVALID_STATE_ERR: 11 + }; + + DOMException.prototype.toString = function() { + return this.message; + }; + + api.dom = { + arrayContains: arrayContains, + isHtmlNamespace: isHtmlNamespace, + parentElement: parentElement, + getNodeIndex: getNodeIndex, + getNodeLength: getNodeLength, + getCommonAncestor: getCommonAncestor, + isAncestorOf: isAncestorOf, + getClosestAncestorIn: getClosestAncestorIn, + isCharacterDataNode: isCharacterDataNode, + insertAfter: insertAfter, + splitDataNode: splitDataNode, + getDocument: getDocument, + getWindow: getWindow, + getIframeWindow: getIframeWindow, + getIframeDocument: getIframeDocument, + getBody: getBody, + getRootContainer: getRootContainer, + comparePoints: comparePoints, + inspectNode: inspectNode, + fragmentFromNodeChildren: fragmentFromNodeChildren, + createIterator: createIterator, + DomPosition: DomPosition + }; + + api.DOMException = DOMException; +});rangy.createModule("DomRange", function(api, module) { + api.requireModules( ["DomUtil"] ); + + + var dom = api.dom; + var DomPosition = dom.DomPosition; + var DOMException = api.DOMException; + + /*----------------------------------------------------------------------------------------------------------------*/ + + // Utility functions + + function isNonTextPartiallySelected(node, range) { + return (node.nodeType != 3) && + (dom.isAncestorOf(node, range.startContainer, true) || dom.isAncestorOf(node, range.endContainer, true)); + } + + function getRangeDocument(range) { + return dom.getDocument(range.startContainer); + } + + function dispatchEvent(range, type, args) { + var listeners = range._listeners[type]; + if (listeners) { + for (var i = 0, len = listeners.length; i < len; ++i) { + listeners[i].call(range, {target: range, args: args}); + } + } + } + + function getBoundaryBeforeNode(node) { + return new DomPosition(node.parentNode, dom.getNodeIndex(node)); + } + + function getBoundaryAfterNode(node) { + return new DomPosition(node.parentNode, dom.getNodeIndex(node) + 1); + } + + function insertNodeAtPosition(node, n, o) { + var firstNodeInserted = node.nodeType == 11 ? node.firstChild : node; + if (dom.isCharacterDataNode(n)) { + if (o == n.length) { + dom.insertAfter(node, n); + } else { + n.parentNode.insertBefore(node, o == 0 ? n : dom.splitDataNode(n, o)); + } + } else if (o >= n.childNodes.length) { + n.appendChild(node); + } else { + n.insertBefore(node, n.childNodes[o]); + } + return firstNodeInserted; + } + + function cloneSubtree(iterator) { + var partiallySelected; + for (var node, frag = getRangeDocument(iterator.range).createDocumentFragment(), subIterator; node = iterator.next(); ) { + partiallySelected = iterator.isPartiallySelectedSubtree(); + + node = node.cloneNode(!partiallySelected); + if (partiallySelected) { + subIterator = iterator.getSubtreeIterator(); + node.appendChild(cloneSubtree(subIterator)); + subIterator.detach(true); + } + + if (node.nodeType == 10) { // DocumentType + throw new DOMException("HIERARCHY_REQUEST_ERR"); + } + frag.appendChild(node); + } + return frag; + } + + function iterateSubtree(rangeIterator, func, iteratorState) { + var it, n; + iteratorState = iteratorState || { stop: false }; + for (var node, subRangeIterator; node = rangeIterator.next(); ) { + //log.debug("iterateSubtree, partially selected: " + rangeIterator.isPartiallySelectedSubtree(), nodeToString(node)); + if (rangeIterator.isPartiallySelectedSubtree()) { + // The node is partially selected by the Range, so we can use a new RangeIterator on the portion of the + // node selected by the Range. + if (func(node) === false) { + iteratorState.stop = true; + return; + } else { + subRangeIterator = rangeIterator.getSubtreeIterator(); + iterateSubtree(subRangeIterator, func, iteratorState); + subRangeIterator.detach(true); + if (iteratorState.stop) { + return; + } + } + } else { + // The whole node is selected, so we can use efficient DOM iteration to iterate over the node and its + // descendant + it = dom.createIterator(node); + while ( (n = it.next()) ) { + if (func(n) === false) { + iteratorState.stop = true; + return; + } + } + } + } + } + + function deleteSubtree(iterator) { + var subIterator; + while (iterator.next()) { + if (iterator.isPartiallySelectedSubtree()) { + subIterator = iterator.getSubtreeIterator(); + deleteSubtree(subIterator); + subIterator.detach(true); + } else { + iterator.remove(); + } + } + } + + function extractSubtree(iterator) { + + for (var node, frag = getRangeDocument(iterator.range).createDocumentFragment(), subIterator; node = iterator.next(); ) { + + + if (iterator.isPartiallySelectedSubtree()) { + node = node.cloneNode(false); + subIterator = iterator.getSubtreeIterator(); + node.appendChild(extractSubtree(subIterator)); + subIterator.detach(true); + } else { + iterator.remove(); + } + if (node.nodeType == 10) { // DocumentType + throw new DOMException("HIERARCHY_REQUEST_ERR"); + } + frag.appendChild(node); + } + return frag; + } + + function getNodesInRange(range, nodeTypes, filter) { + //log.info("getNodesInRange, " + nodeTypes.join(",")); + var filterNodeTypes = !!(nodeTypes && nodeTypes.length), regex; + var filterExists = !!filter; + if (filterNodeTypes) { + regex = new RegExp("^(" + nodeTypes.join("|") + ")$"); + } + + var nodes = []; + iterateSubtree(new RangeIterator(range, false), function(node) { + if ((!filterNodeTypes || regex.test(node.nodeType)) && (!filterExists || filter(node))) { + nodes.push(node); + } + }); + return nodes; + } + + function inspect(range) { + var name = (typeof range.getName == "undefined") ? "Range" : range.getName(); + return "[" + name + "(" + dom.inspectNode(range.startContainer) + ":" + range.startOffset + ", " + + dom.inspectNode(range.endContainer) + ":" + range.endOffset + ")]"; + } + + /*----------------------------------------------------------------------------------------------------------------*/ + + // RangeIterator code partially borrows from IERange by Tim Ryan (http://github.com/timcameronryan/IERange) + + /** + * @constructor + */ + function RangeIterator(range, clonePartiallySelectedTextNodes) { + this.range = range; + this.clonePartiallySelectedTextNodes = clonePartiallySelectedTextNodes; + + + + if (!range.collapsed) { + this.sc = range.startContainer; + this.so = range.startOffset; + this.ec = range.endContainer; + this.eo = range.endOffset; + var root = range.commonAncestorContainer; + + if (this.sc === this.ec && dom.isCharacterDataNode(this.sc)) { + this.isSingleCharacterDataNode = true; + this._first = this._last = this._next = this.sc; + } else { + this._first = this._next = (this.sc === root && !dom.isCharacterDataNode(this.sc)) ? + this.sc.childNodes[this.so] : dom.getClosestAncestorIn(this.sc, root, true); + this._last = (this.ec === root && !dom.isCharacterDataNode(this.ec)) ? + this.ec.childNodes[this.eo - 1] : dom.getClosestAncestorIn(this.ec, root, true); + } + + } + } + + RangeIterator.prototype = { + _current: null, + _next: null, + _first: null, + _last: null, + isSingleCharacterDataNode: false, + + reset: function() { + this._current = null; + this._next = this._first; + }, + + hasNext: function() { + return !!this._next; + }, + + next: function() { + // Move to next node + var current = this._current = this._next; + if (current) { + this._next = (current !== this._last) ? current.nextSibling : null; + + // Check for partially selected text nodes + if (dom.isCharacterDataNode(current) && this.clonePartiallySelectedTextNodes) { + if (current === this.ec) { + + (current = current.cloneNode(true)).deleteData(this.eo, current.length - this.eo); + } + if (this._current === this.sc) { + + (current = current.cloneNode(true)).deleteData(0, this.so); + } + } + } + + return current; + }, + + remove: function() { + var current = this._current, start, end; + + if (dom.isCharacterDataNode(current) && (current === this.sc || current === this.ec)) { + start = (current === this.sc) ? this.so : 0; + end = (current === this.ec) ? this.eo : current.length; + if (start != end) { + current.deleteData(start, end - start); + } + } else { + if (current.parentNode) { + current.parentNode.removeChild(current); + } else { + + } + } + }, + + // Checks if the current node is partially selected + isPartiallySelectedSubtree: function() { + var current = this._current; + return isNonTextPartiallySelected(current, this.range); + }, + + getSubtreeIterator: function() { + var subRange; + if (this.isSingleCharacterDataNode) { + subRange = this.range.cloneRange(); + subRange.collapse(); + } else { + subRange = new Range(getRangeDocument(this.range)); + var current = this._current; + var startContainer = current, startOffset = 0, endContainer = current, endOffset = dom.getNodeLength(current); + + if (dom.isAncestorOf(current, this.sc, true)) { + startContainer = this.sc; + startOffset = this.so; + } + if (dom.isAncestorOf(current, this.ec, true)) { + endContainer = this.ec; + endOffset = this.eo; + } + + updateBoundaries(subRange, startContainer, startOffset, endContainer, endOffset); + } + return new RangeIterator(subRange, this.clonePartiallySelectedTextNodes); + }, + + detach: function(detachRange) { + if (detachRange) { + this.range.detach(); + } + this.range = this._current = this._next = this._first = this._last = this.sc = this.so = this.ec = this.eo = null; + } + }; + + /*----------------------------------------------------------------------------------------------------------------*/ + + // Exceptions + + /** + * @constructor + */ + function RangeException(codeName) { + this.code = this[codeName]; + this.codeName = codeName; + this.message = "RangeException: " + this.codeName; + } + + RangeException.prototype = { + BAD_BOUNDARYPOINTS_ERR: 1, + INVALID_NODE_TYPE_ERR: 2 + }; + + RangeException.prototype.toString = function() { + return this.message; + }; + + /*----------------------------------------------------------------------------------------------------------------*/ + + /** + * Currently iterates through all nodes in the range on creation until I think of a decent way to do it + * TODO: Look into making this a proper iterator, not requiring preloading everything first + * @constructor + */ + function RangeNodeIterator(range, nodeTypes, filter) { + this.nodes = getNodesInRange(range, nodeTypes, filter); + this._next = this.nodes[0]; + this._position = 0; + } + + RangeNodeIterator.prototype = { + _current: null, + + hasNext: function() { + return !!this._next; + }, + + next: function() { + this._current = this._next; + this._next = this.nodes[ ++this._position ]; + return this._current; + }, + + detach: function() { + this._current = this._next = this.nodes = null; + } + }; + + var beforeAfterNodeTypes = [1, 3, 4, 5, 7, 8, 10]; + var rootContainerNodeTypes = [2, 9, 11]; + var readonlyNodeTypes = [5, 6, 10, 12]; + var insertableNodeTypes = [1, 3, 4, 5, 7, 8, 10, 11]; + var surroundNodeTypes = [1, 3, 4, 5, 7, 8]; + + function createAncestorFinder(nodeTypes) { + return function(node, selfIsAncestor) { + var t, n = selfIsAncestor ? node : node.parentNode; + while (n) { + t = n.nodeType; + if (dom.arrayContains(nodeTypes, t)) { + return n; + } + n = n.parentNode; + } + return null; + }; + } + + var getRootContainer = dom.getRootContainer; + var getDocumentOrFragmentContainer = createAncestorFinder( [9, 11] ); + var getReadonlyAncestor = createAncestorFinder(readonlyNodeTypes); + var getDocTypeNotationEntityAncestor = createAncestorFinder( [6, 10, 12] ); + + function assertNoDocTypeNotationEntityAncestor(node, allowSelf) { + if (getDocTypeNotationEntityAncestor(node, allowSelf)) { + throw new RangeException("INVALID_NODE_TYPE_ERR"); + } + } + + function assertNotDetached(range) { + if (!range.startContainer) { + throw new DOMException("INVALID_STATE_ERR"); + } + } + + function assertValidNodeType(node, invalidTypes) { + if (!dom.arrayContains(invalidTypes, node.nodeType)) { + throw new RangeException("INVALID_NODE_TYPE_ERR"); + } + } + + function assertValidOffset(node, offset) { + if (offset < 0 || offset > (dom.isCharacterDataNode(node) ? node.length : node.childNodes.length)) { + throw new DOMException("INDEX_SIZE_ERR"); + } + } + + function assertSameDocumentOrFragment(node1, node2) { + if (getDocumentOrFragmentContainer(node1, true) !== getDocumentOrFragmentContainer(node2, true)) { + throw new DOMException("WRONG_DOCUMENT_ERR"); + } + } + + function assertNodeNotReadOnly(node) { + if (getReadonlyAncestor(node, true)) { + throw new DOMException("NO_MODIFICATION_ALLOWED_ERR"); + } + } + + function assertNode(node, codeName) { + if (!node) { + throw new DOMException(codeName); + } + } + + function isOrphan(node) { + return !dom.arrayContains(rootContainerNodeTypes, node.nodeType) && !getDocumentOrFragmentContainer(node, true); + } + + function isValidOffset(node, offset) { + return offset <= (dom.isCharacterDataNode(node) ? node.length : node.childNodes.length); + } + + function assertRangeValid(range) { + assertNotDetached(range); + if (isOrphan(range.startContainer) || isOrphan(range.endContainer) || + !isValidOffset(range.startContainer, range.startOffset) || + !isValidOffset(range.endContainer, range.endOffset)) { + throw new Error("Range error: Range is no longer valid after DOM mutation (" + range.inspect() + ")"); + } + } + + /*----------------------------------------------------------------------------------------------------------------*/ + + // Test the browser's innerHTML support to decide how to implement createContextualFragment + var styleEl = document.createElement("style"); + var htmlParsingConforms = false; + try { + styleEl.innerHTML = "x"; + htmlParsingConforms = (styleEl.firstChild.nodeType == 3); // Opera incorrectly creates an element node + } catch (e) { + // IE 6 and 7 throw + } + + api.features.htmlParsingConforms = htmlParsingConforms; + + var createContextualFragment = htmlParsingConforms ? + + // Implementation as per HTML parsing spec, trusting in the browser's implementation of innerHTML. See + // discussion and base code for this implementation at issue 67. + // Spec: http://html5.org/specs/dom-parsing.html#extensions-to-the-range-interface + // Thanks to Aleks Williams. + function(fragmentStr) { + // "Let node the context object's start's node." + var node = this.startContainer; + var doc = dom.getDocument(node); + + // "If the context object's start's node is null, raise an INVALID_STATE_ERR + // exception and abort these steps." + if (!node) { + throw new DOMException("INVALID_STATE_ERR"); + } + + // "Let element be as follows, depending on node's interface:" + // Document, Document Fragment: null + var el = null; + + // "Element: node" + if (node.nodeType == 1) { + el = node; + + // "Text, Comment: node's parentElement" + } else if (dom.isCharacterDataNode(node)) { + el = dom.parentElement(node); + } + + // "If either element is null or element's ownerDocument is an HTML document + // and element's local name is "html" and element's namespace is the HTML + // namespace" + if (el === null || ( + el.nodeName == "HTML" + && dom.isHtmlNamespace(dom.getDocument(el).documentElement) + && dom.isHtmlNamespace(el) + )) { + + // "let element be a new Element with "body" as its local name and the HTML + // namespace as its namespace."" + el = doc.createElement("body"); + } else { + el = el.cloneNode(false); + } + + // "If the node's document is an HTML document: Invoke the HTML fragment parsing algorithm." + // "If the node's document is an XML document: Invoke the XML fragment parsing algorithm." + // "In either case, the algorithm must be invoked with fragment as the input + // and element as the context element." + el.innerHTML = fragmentStr; + + // "If this raises an exception, then abort these steps. Otherwise, let new + // children be the nodes returned." + + // "Let fragment be a new DocumentFragment." + // "Append all new children to fragment." + // "Return fragment." + return dom.fragmentFromNodeChildren(el); + } : + + // In this case, innerHTML cannot be trusted, so fall back to a simpler, non-conformant implementation that + // previous versions of Rangy used (with the exception of using a body element rather than a div) + function(fragmentStr) { + assertNotDetached(this); + var doc = getRangeDocument(this); + var el = doc.createElement("body"); + el.innerHTML = fragmentStr; + + return dom.fragmentFromNodeChildren(el); + }; + + /*----------------------------------------------------------------------------------------------------------------*/ + + var rangeProperties = ["startContainer", "startOffset", "endContainer", "endOffset", "collapsed", + "commonAncestorContainer"]; + + var s2s = 0, s2e = 1, e2e = 2, e2s = 3; + var n_b = 0, n_a = 1, n_b_a = 2, n_i = 3; + + function RangePrototype() {} + + RangePrototype.prototype = { + attachListener: function(type, listener) { + this._listeners[type].push(listener); + }, + + compareBoundaryPoints: function(how, range) { + assertRangeValid(this); + assertSameDocumentOrFragment(this.startContainer, range.startContainer); + + var nodeA, offsetA, nodeB, offsetB; + var prefixA = (how == e2s || how == s2s) ? "start" : "end"; + var prefixB = (how == s2e || how == s2s) ? "start" : "end"; + nodeA = this[prefixA + "Container"]; + offsetA = this[prefixA + "Offset"]; + nodeB = range[prefixB + "Container"]; + offsetB = range[prefixB + "Offset"]; + return dom.comparePoints(nodeA, offsetA, nodeB, offsetB); + }, + + insertNode: function(node) { + assertRangeValid(this); + assertValidNodeType(node, insertableNodeTypes); + assertNodeNotReadOnly(this.startContainer); + + if (dom.isAncestorOf(node, this.startContainer, true)) { + throw new DOMException("HIERARCHY_REQUEST_ERR"); + } + + // No check for whether the container of the start of the Range is of a type that does not allow + // children of the type of node: the browser's DOM implementation should do this for us when we attempt + // to add the node + + var firstNodeInserted = insertNodeAtPosition(node, this.startContainer, this.startOffset); + this.setStartBefore(firstNodeInserted); + }, + + cloneContents: function() { + assertRangeValid(this); + + var clone, frag; + if (this.collapsed) { + return getRangeDocument(this).createDocumentFragment(); + } else { + if (this.startContainer === this.endContainer && dom.isCharacterDataNode(this.startContainer)) { + clone = this.startContainer.cloneNode(true); + clone.data = clone.data.slice(this.startOffset, this.endOffset); + frag = getRangeDocument(this).createDocumentFragment(); + frag.appendChild(clone); + return frag; + } else { + var iterator = new RangeIterator(this, true); + clone = cloneSubtree(iterator); + iterator.detach(); + } + return clone; + } + }, + + canSurroundContents: function() { + assertRangeValid(this); + assertNodeNotReadOnly(this.startContainer); + assertNodeNotReadOnly(this.endContainer); + + // Check if the contents can be surrounded. Specifically, this means whether the range partially selects + // no non-text nodes. + var iterator = new RangeIterator(this, true); + var boundariesInvalid = (iterator._first && (isNonTextPartiallySelected(iterator._first, this)) || + (iterator._last && isNonTextPartiallySelected(iterator._last, this))); + iterator.detach(); + return !boundariesInvalid; + }, + + surroundContents: function(node) { + assertValidNodeType(node, surroundNodeTypes); + + if (!this.canSurroundContents()) { + throw new RangeException("BAD_BOUNDARYPOINTS_ERR"); + } + + // Extract the contents + var content = this.extractContents(); + + // Clear the children of the node + if (node.hasChildNodes()) { + while (node.lastChild) { + node.removeChild(node.lastChild); + } + } + + // Insert the new node and add the extracted contents + insertNodeAtPosition(node, this.startContainer, this.startOffset); + node.appendChild(content); + + this.selectNode(node); + }, + + cloneRange: function() { + assertRangeValid(this); + var range = new Range(getRangeDocument(this)); + var i = rangeProperties.length, prop; + while (i--) { + prop = rangeProperties[i]; + range[prop] = this[prop]; + } + return range; + }, + + toString: function() { + assertRangeValid(this); + var sc = this.startContainer; + if (sc === this.endContainer && dom.isCharacterDataNode(sc)) { + return (sc.nodeType == 3 || sc.nodeType == 4) ? sc.data.slice(this.startOffset, this.endOffset) : ""; + } else { + var textBits = [], iterator = new RangeIterator(this, true); + + iterateSubtree(iterator, function(node) { + // Accept only text or CDATA nodes, not comments + + if (node.nodeType == 3 || node.nodeType == 4) { + textBits.push(node.data); + } + }); + iterator.detach(); + return textBits.join(""); + } + }, + + // The methods below are all non-standard. The following batch were introduced by Mozilla but have since + // been removed from Mozilla. + + compareNode: function(node) { + assertRangeValid(this); + + var parent = node.parentNode; + var nodeIndex = dom.getNodeIndex(node); + + if (!parent) { + throw new DOMException("NOT_FOUND_ERR"); + } + + var startComparison = this.comparePoint(parent, nodeIndex), + endComparison = this.comparePoint(parent, nodeIndex + 1); + + if (startComparison < 0) { // Node starts before + return (endComparison > 0) ? n_b_a : n_b; + } else { + return (endComparison > 0) ? n_a : n_i; + } + }, + + comparePoint: function(node, offset) { + assertRangeValid(this); + assertNode(node, "HIERARCHY_REQUEST_ERR"); + assertSameDocumentOrFragment(node, this.startContainer); + + if (dom.comparePoints(node, offset, this.startContainer, this.startOffset) < 0) { + return -1; + } else if (dom.comparePoints(node, offset, this.endContainer, this.endOffset) > 0) { + return 1; + } + return 0; + }, + + createContextualFragment: createContextualFragment, + + toHtml: function() { + assertRangeValid(this); + var container = getRangeDocument(this).createElement("div"); + container.appendChild(this.cloneContents()); + return container.innerHTML; + }, + + // touchingIsIntersecting determines whether this method considers a node that borders a range intersects + // with it (as in WebKit) or not (as in Gecko pre-1.9, and the default) + intersectsNode: function(node, touchingIsIntersecting) { + assertRangeValid(this); + assertNode(node, "NOT_FOUND_ERR"); + if (dom.getDocument(node) !== getRangeDocument(this)) { + return false; + } + + var parent = node.parentNode, offset = dom.getNodeIndex(node); + assertNode(parent, "NOT_FOUND_ERR"); + + var startComparison = dom.comparePoints(parent, offset, this.endContainer, this.endOffset), + endComparison = dom.comparePoints(parent, offset + 1, this.startContainer, this.startOffset); + + return touchingIsIntersecting ? startComparison <= 0 && endComparison >= 0 : startComparison < 0 && endComparison > 0; + }, + + + isPointInRange: function(node, offset) { + assertRangeValid(this); + assertNode(node, "HIERARCHY_REQUEST_ERR"); + assertSameDocumentOrFragment(node, this.startContainer); + + return (dom.comparePoints(node, offset, this.startContainer, this.startOffset) >= 0) && + (dom.comparePoints(node, offset, this.endContainer, this.endOffset) <= 0); + }, + + // The methods below are non-standard and invented by me. + + // Sharing a boundary start-to-end or end-to-start does not count as intersection. + intersectsRange: function(range, touchingIsIntersecting) { + assertRangeValid(this); + + if (getRangeDocument(range) != getRangeDocument(this)) { + throw new DOMException("WRONG_DOCUMENT_ERR"); + } + + var startComparison = dom.comparePoints(this.startContainer, this.startOffset, range.endContainer, range.endOffset), + endComparison = dom.comparePoints(this.endContainer, this.endOffset, range.startContainer, range.startOffset); + + return touchingIsIntersecting ? startComparison <= 0 && endComparison >= 0 : startComparison < 0 && endComparison > 0; + }, + + intersection: function(range) { + if (this.intersectsRange(range)) { + var startComparison = dom.comparePoints(this.startContainer, this.startOffset, range.startContainer, range.startOffset), + endComparison = dom.comparePoints(this.endContainer, this.endOffset, range.endContainer, range.endOffset); + + var intersectionRange = this.cloneRange(); + + if (startComparison == -1) { + intersectionRange.setStart(range.startContainer, range.startOffset); + } + if (endComparison == 1) { + intersectionRange.setEnd(range.endContainer, range.endOffset); + } + return intersectionRange; + } + return null; + }, + + union: function(range) { + if (this.intersectsRange(range, true)) { + var unionRange = this.cloneRange(); + if (dom.comparePoints(range.startContainer, range.startOffset, this.startContainer, this.startOffset) == -1) { + unionRange.setStart(range.startContainer, range.startOffset); + } + if (dom.comparePoints(range.endContainer, range.endOffset, this.endContainer, this.endOffset) == 1) { + unionRange.setEnd(range.endContainer, range.endOffset); + } + return unionRange; + } else { + throw new RangeException("Ranges do not intersect"); + } + }, + + containsNode: function(node, allowPartial) { + if (allowPartial) { + return this.intersectsNode(node, false); + } else { + return this.compareNode(node) == n_i; + } + }, + + containsNodeContents: function(node) { + return this.comparePoint(node, 0) >= 0 && this.comparePoint(node, dom.getNodeLength(node)) <= 0; + }, + + containsRange: function(range) { + return this.intersection(range).equals(range); + }, + + containsNodeText: function(node) { + var nodeRange = this.cloneRange(); + nodeRange.selectNode(node); + var textNodes = nodeRange.getNodes([3]); + if (textNodes.length > 0) { + nodeRange.setStart(textNodes[0], 0); + var lastTextNode = textNodes.pop(); + nodeRange.setEnd(lastTextNode, lastTextNode.length); + var contains = this.containsRange(nodeRange); + nodeRange.detach(); + return contains; + } else { + return this.containsNodeContents(node); + } + }, + + createNodeIterator: function(nodeTypes, filter) { + assertRangeValid(this); + return new RangeNodeIterator(this, nodeTypes, filter); + }, + + getNodes: function(nodeTypes, filter) { + assertRangeValid(this); + return getNodesInRange(this, nodeTypes, filter); + }, + + getDocument: function() { + return getRangeDocument(this); + }, + + collapseBefore: function(node) { + assertNotDetached(this); + + this.setEndBefore(node); + this.collapse(false); + }, + + collapseAfter: function(node) { + assertNotDetached(this); + + this.setStartAfter(node); + this.collapse(true); + }, + + getName: function() { + return "DomRange"; + }, + + equals: function(range) { + return Range.rangesEqual(this, range); + }, + + inspect: function() { + return inspect(this); + } + }; + + function copyComparisonConstantsToObject(obj) { + obj.START_TO_START = s2s; + obj.START_TO_END = s2e; + obj.END_TO_END = e2e; + obj.END_TO_START = e2s; + + obj.NODE_BEFORE = n_b; + obj.NODE_AFTER = n_a; + obj.NODE_BEFORE_AND_AFTER = n_b_a; + obj.NODE_INSIDE = n_i; + } + + function copyComparisonConstants(constructor) { + copyComparisonConstantsToObject(constructor); + copyComparisonConstantsToObject(constructor.prototype); + } + + function createRangeContentRemover(remover, boundaryUpdater) { + return function() { + assertRangeValid(this); + + var sc = this.startContainer, so = this.startOffset, root = this.commonAncestorContainer; + + var iterator = new RangeIterator(this, true); + + // Work out where to position the range after content removal + var node, boundary; + if (sc !== root) { + node = dom.getClosestAncestorIn(sc, root, true); + boundary = getBoundaryAfterNode(node); + sc = boundary.node; + so = boundary.offset; + } + + // Check none of the range is read-only + iterateSubtree(iterator, assertNodeNotReadOnly); + + iterator.reset(); + + // Remove the content + var returnValue = remover(iterator); + iterator.detach(); + + // Move to the new position + boundaryUpdater(this, sc, so, sc, so); + + return returnValue; + }; + } + + function createPrototypeRange(constructor, boundaryUpdater, detacher) { + function createBeforeAfterNodeSetter(isBefore, isStart) { + return function(node) { + assertNotDetached(this); + assertValidNodeType(node, beforeAfterNodeTypes); + assertValidNodeType(getRootContainer(node), rootContainerNodeTypes); + + var boundary = (isBefore ? getBoundaryBeforeNode : getBoundaryAfterNode)(node); + (isStart ? setRangeStart : setRangeEnd)(this, boundary.node, boundary.offset); + }; + } + + function setRangeStart(range, node, offset) { + var ec = range.endContainer, eo = range.endOffset; + if (node !== range.startContainer || offset !== range.startOffset) { + // Check the root containers of the range and the new boundary, and also check whether the new boundary + // is after the current end. In either case, collapse the range to the new position + if (getRootContainer(node) != getRootContainer(ec) || dom.comparePoints(node, offset, ec, eo) == 1) { + ec = node; + eo = offset; + } + boundaryUpdater(range, node, offset, ec, eo); + } + } + + function setRangeEnd(range, node, offset) { + var sc = range.startContainer, so = range.startOffset; + if (node !== range.endContainer || offset !== range.endOffset) { + // Check the root containers of the range and the new boundary, and also check whether the new boundary + // is after the current end. In either case, collapse the range to the new position + if (getRootContainer(node) != getRootContainer(sc) || dom.comparePoints(node, offset, sc, so) == -1) { + sc = node; + so = offset; + } + boundaryUpdater(range, sc, so, node, offset); + } + } + + function setRangeStartAndEnd(range, node, offset) { + if (node !== range.startContainer || offset !== range.startOffset || node !== range.endContainer || offset !== range.endOffset) { + boundaryUpdater(range, node, offset, node, offset); + } + } + + constructor.prototype = new RangePrototype(); + + api.util.extend(constructor.prototype, { + setStart: function(node, offset) { + assertNotDetached(this); + assertNoDocTypeNotationEntityAncestor(node, true); + assertValidOffset(node, offset); + + setRangeStart(this, node, offset); + }, + + setEnd: function(node, offset) { + assertNotDetached(this); + assertNoDocTypeNotationEntityAncestor(node, true); + assertValidOffset(node, offset); + + setRangeEnd(this, node, offset); + }, + + setStartBefore: createBeforeAfterNodeSetter(true, true), + setStartAfter: createBeforeAfterNodeSetter(false, true), + setEndBefore: createBeforeAfterNodeSetter(true, false), + setEndAfter: createBeforeAfterNodeSetter(false, false), + + collapse: function(isStart) { + assertRangeValid(this); + if (isStart) { + boundaryUpdater(this, this.startContainer, this.startOffset, this.startContainer, this.startOffset); + } else { + boundaryUpdater(this, this.endContainer, this.endOffset, this.endContainer, this.endOffset); + } + }, + + selectNodeContents: function(node) { + // This doesn't seem well specified: the spec talks only about selecting the node's contents, which + // could be taken to mean only its children. However, browsers implement this the same as selectNode for + // text nodes, so I shall do likewise + assertNotDetached(this); + assertNoDocTypeNotationEntityAncestor(node, true); + + boundaryUpdater(this, node, 0, node, dom.getNodeLength(node)); + }, + + selectNode: function(node) { + assertNotDetached(this); + assertNoDocTypeNotationEntityAncestor(node, false); + assertValidNodeType(node, beforeAfterNodeTypes); + + var start = getBoundaryBeforeNode(node), end = getBoundaryAfterNode(node); + boundaryUpdater(this, start.node, start.offset, end.node, end.offset); + }, + + extractContents: createRangeContentRemover(extractSubtree, boundaryUpdater), + + deleteContents: createRangeContentRemover(deleteSubtree, boundaryUpdater), + + canSurroundContents: function() { + assertRangeValid(this); + assertNodeNotReadOnly(this.startContainer); + assertNodeNotReadOnly(this.endContainer); + + // Check if the contents can be surrounded. Specifically, this means whether the range partially selects + // no non-text nodes. + var iterator = new RangeIterator(this, true); + var boundariesInvalid = (iterator._first && (isNonTextPartiallySelected(iterator._first, this)) || + (iterator._last && isNonTextPartiallySelected(iterator._last, this))); + iterator.detach(); + return !boundariesInvalid; + }, + + detach: function() { + detacher(this); + }, + + splitBoundaries: function() { + assertRangeValid(this); + + + var sc = this.startContainer, so = this.startOffset, ec = this.endContainer, eo = this.endOffset; + var startEndSame = (sc === ec); + + if (dom.isCharacterDataNode(ec) && eo > 0 && eo < ec.length) { + dom.splitDataNode(ec, eo); + + } + + if (dom.isCharacterDataNode(sc) && so > 0 && so < sc.length) { + + sc = dom.splitDataNode(sc, so); + if (startEndSame) { + eo -= so; + ec = sc; + } else if (ec == sc.parentNode && eo >= dom.getNodeIndex(sc)) { + eo++; + } + so = 0; + + } + boundaryUpdater(this, sc, so, ec, eo); + }, + + normalizeBoundaries: function() { + assertRangeValid(this); + + var sc = this.startContainer, so = this.startOffset, ec = this.endContainer, eo = this.endOffset; + + var mergeForward = function(node) { + var sibling = node.nextSibling; + if (sibling && sibling.nodeType == node.nodeType) { + ec = node; + eo = node.length; + node.appendData(sibling.data); + sibling.parentNode.removeChild(sibling); + } + }; + + var mergeBackward = function(node) { + var sibling = node.previousSibling; + if (sibling && sibling.nodeType == node.nodeType) { + sc = node; + var nodeLength = node.length; + so = sibling.length; + node.insertData(0, sibling.data); + sibling.parentNode.removeChild(sibling); + if (sc == ec) { + eo += so; + ec = sc; + } else if (ec == node.parentNode) { + var nodeIndex = dom.getNodeIndex(node); + if (eo == nodeIndex) { + ec = node; + eo = nodeLength; + } else if (eo > nodeIndex) { + eo--; + } + } + } + }; + + var normalizeStart = true; + + if (dom.isCharacterDataNode(ec)) { + if (ec.length == eo) { + mergeForward(ec); + } + } else { + if (eo > 0) { + var endNode = ec.childNodes[eo - 1]; + if (endNode && dom.isCharacterDataNode(endNode)) { + mergeForward(endNode); + } + } + normalizeStart = !this.collapsed; + } + + if (normalizeStart) { + if (dom.isCharacterDataNode(sc)) { + if (so == 0) { + mergeBackward(sc); + } + } else { + if (so < sc.childNodes.length) { + var startNode = sc.childNodes[so]; + if (startNode && dom.isCharacterDataNode(startNode)) { + mergeBackward(startNode); + } + } + } + } else { + sc = ec; + so = eo; + } + + boundaryUpdater(this, sc, so, ec, eo); + }, + + collapseToPoint: function(node, offset) { + assertNotDetached(this); + + assertNoDocTypeNotationEntityAncestor(node, true); + assertValidOffset(node, offset); + + setRangeStartAndEnd(this, node, offset); + } + }); + + copyComparisonConstants(constructor); + } + + /*----------------------------------------------------------------------------------------------------------------*/ + + // Updates commonAncestorContainer and collapsed after boundary change + function updateCollapsedAndCommonAncestor(range) { + range.collapsed = (range.startContainer === range.endContainer && range.startOffset === range.endOffset); + range.commonAncestorContainer = range.collapsed ? + range.startContainer : dom.getCommonAncestor(range.startContainer, range.endContainer); + } + + function updateBoundaries(range, startContainer, startOffset, endContainer, endOffset) { + var startMoved = (range.startContainer !== startContainer || range.startOffset !== startOffset); + var endMoved = (range.endContainer !== endContainer || range.endOffset !== endOffset); + + range.startContainer = startContainer; + range.startOffset = startOffset; + range.endContainer = endContainer; + range.endOffset = endOffset; + + updateCollapsedAndCommonAncestor(range); + dispatchEvent(range, "boundarychange", {startMoved: startMoved, endMoved: endMoved}); + } + + function detach(range) { + assertNotDetached(range); + range.startContainer = range.startOffset = range.endContainer = range.endOffset = null; + range.collapsed = range.commonAncestorContainer = null; + dispatchEvent(range, "detach", null); + range._listeners = null; + } + + /** + * @constructor + */ + function Range(doc) { + this.startContainer = doc; + this.startOffset = 0; + this.endContainer = doc; + this.endOffset = 0; + this._listeners = { + boundarychange: [], + detach: [] + }; + updateCollapsedAndCommonAncestor(this); + } + + createPrototypeRange(Range, updateBoundaries, detach); + + api.rangePrototype = RangePrototype.prototype; + + Range.rangeProperties = rangeProperties; + Range.RangeIterator = RangeIterator; + Range.copyComparisonConstants = copyComparisonConstants; + Range.createPrototypeRange = createPrototypeRange; + Range.inspect = inspect; + Range.getRangeDocument = getRangeDocument; + Range.rangesEqual = function(r1, r2) { + return r1.startContainer === r2.startContainer && + r1.startOffset === r2.startOffset && + r1.endContainer === r2.endContainer && + r1.endOffset === r2.endOffset; + }; + + api.DomRange = Range; + api.RangeException = RangeException; +});rangy.createModule("WrappedRange", function(api, module) { + api.requireModules( ["DomUtil", "DomRange"] ); + + /** + * @constructor + */ + var WrappedRange; + var dom = api.dom; + var DomPosition = dom.DomPosition; + var DomRange = api.DomRange; + + + + /*----------------------------------------------------------------------------------------------------------------*/ + + /* + This is a workaround for a bug where IE returns the wrong container element from the TextRange's parentElement() + method. For example, in the following (where pipes denote the selection boundaries): + +
          • | a
          • b |
          + + var range = document.selection.createRange(); + alert(range.parentElement().id); // Should alert "ul" but alerts "b" + + This method returns the common ancestor node of the following: + - the parentElement() of the textRange + - the parentElement() of the textRange after calling collapse(true) + - the parentElement() of the textRange after calling collapse(false) + */ + function getTextRangeContainerElement(textRange) { + var parentEl = textRange.parentElement(); + + var range = textRange.duplicate(); + range.collapse(true); + var startEl = range.parentElement(); + range = textRange.duplicate(); + range.collapse(false); + var endEl = range.parentElement(); + var startEndContainer = (startEl == endEl) ? startEl : dom.getCommonAncestor(startEl, endEl); + + return startEndContainer == parentEl ? startEndContainer : dom.getCommonAncestor(parentEl, startEndContainer); + } + + function textRangeIsCollapsed(textRange) { + return textRange.compareEndPoints("StartToEnd", textRange) == 0; + } + + // Gets the boundary of a TextRange expressed as a node and an offset within that node. This function started out as + // an improved version of code found in Tim Cameron Ryan's IERange (http://code.google.com/p/ierange/) but has + // grown, fixing problems with line breaks in preformatted text, adding workaround for IE TextRange bugs, handling + // for inputs and images, plus optimizations. + function getTextRangeBoundaryPosition(textRange, wholeRangeContainerElement, isStart, isCollapsed) { + var workingRange = textRange.duplicate(); + + workingRange.collapse(isStart); + var containerElement = workingRange.parentElement(); + + // Sometimes collapsing a TextRange that's at the start of a text node can move it into the previous node, so + // check for that + // TODO: Find out when. Workaround for wholeRangeContainerElement may break this + if (!dom.isAncestorOf(wholeRangeContainerElement, containerElement, true)) { + containerElement = wholeRangeContainerElement; + + } + + + + // Deal with nodes that cannot "contain rich HTML markup". In practice, this means form inputs, images and + // similar. See http://msdn.microsoft.com/en-us/library/aa703950%28VS.85%29.aspx + if (!containerElement.canHaveHTML) { + return new DomPosition(containerElement.parentNode, dom.getNodeIndex(containerElement)); + } + + var workingNode = dom.getDocument(containerElement).createElement("span"); + var comparison, workingComparisonType = isStart ? "StartToStart" : "StartToEnd"; + var previousNode, nextNode, boundaryPosition, boundaryNode; + + // Move the working range through the container's children, starting at the end and working backwards, until the + // working range reaches or goes past the boundary we're interested in + do { + containerElement.insertBefore(workingNode, workingNode.previousSibling); + workingRange.moveToElementText(workingNode); + } while ( (comparison = workingRange.compareEndPoints(workingComparisonType, textRange)) > 0 && + workingNode.previousSibling); + + // We've now reached or gone past the boundary of the text range we're interested in + // so have identified the node we want + boundaryNode = workingNode.nextSibling; + + if (comparison == -1 && boundaryNode && dom.isCharacterDataNode(boundaryNode)) { + // This is a character data node (text, comment, cdata). The working range is collapsed at the start of the + // node containing the text range's boundary, so we move the end of the working range to the boundary point + // and measure the length of its text to get the boundary's offset within the node. + workingRange.setEndPoint(isStart ? "EndToStart" : "EndToEnd", textRange); + + + var offset; + + if (/[\r\n]/.test(boundaryNode.data)) { + /* + For the particular case of a boundary within a text node containing line breaks (within a
           element,
          +                for example), we need a slightly complicated approach to get the boundary's offset in IE. The facts:
          +
          +                - Each line break is represented as \r in the text node's data/nodeValue properties
          +                - Each line break is represented as \r\n in the TextRange's 'text' property
          +                - The 'text' property of the TextRange does not contain trailing line breaks
          +
          +                To get round the problem presented by the final fact above, we can use the fact that TextRange's
          +                moveStart() and moveEnd() methods return the actual number of characters moved, which is not necessarily
          +                the same as the number of characters it was instructed to move. The simplest approach is to use this to
          +                store the characters moved when moving both the start and end of the range to the start of the document
          +                body and subtracting the start offset from the end offset (the "move-negative-gazillion" method).
          +                However, this is extremely slow when the document is large and the range is near the end of it. Clearly
          +                doing the mirror image (i.e. moving the range boundaries to the end of the document) has the same
          +                problem.
          +
          +                Another approach that works is to use moveStart() to move the start boundary of the range up to the end
          +                boundary one character at a time and incrementing a counter with the value returned by the moveStart()
          +                call. However, the check for whether the start boundary has reached the end boundary is expensive, so
          +                this method is slow (although unlike "move-negative-gazillion" is largely unaffected by the location of
          +                the range within the document).
          +
          +                The method below is a hybrid of the two methods above. It uses the fact that a string containing the
          +                TextRange's 'text' property with each \r\n converted to a single \r character cannot be longer than the
          +                text of the TextRange, so the start of the range is moved that length initially and then a character at
          +                a time to make up for any trailing line breaks not contained in the 'text' property. This has good
          +                performance in most situations compared to the previous two methods.
          +                */
          +                var tempRange = workingRange.duplicate();
          +                var rangeLength = tempRange.text.replace(/\r\n/g, "\r").length;
          +
          +                offset = tempRange.moveStart("character", rangeLength);
          +                while ( (comparison = tempRange.compareEndPoints("StartToEnd", tempRange)) == -1) {
          +                    offset++;
          +                    tempRange.moveStart("character", 1);
          +                }
          +            } else {
          +                offset = workingRange.text.length;
          +            }
          +            boundaryPosition = new DomPosition(boundaryNode, offset);
          +        } else {
          +
          +
          +            // If the boundary immediately follows a character data node and this is the end boundary, we should favour
          +            // a position within that, and likewise for a start boundary preceding a character data node
          +            previousNode = (isCollapsed || !isStart) && workingNode.previousSibling;
          +            nextNode = (isCollapsed || isStart) && workingNode.nextSibling;
          +
          +
          +
          +            if (nextNode && dom.isCharacterDataNode(nextNode)) {
          +                boundaryPosition = new DomPosition(nextNode, 0);
          +            } else if (previousNode && dom.isCharacterDataNode(previousNode)) {
          +                boundaryPosition = new DomPosition(previousNode, previousNode.length);
          +            } else {
          +                boundaryPosition = new DomPosition(containerElement, dom.getNodeIndex(workingNode));
          +            }
          +        }
          +
          +        // Clean up
          +        workingNode.parentNode.removeChild(workingNode);
          +
          +        return boundaryPosition;
          +    }
          +
          +    // Returns a TextRange representing the boundary of a TextRange expressed as a node and an offset within that node.
          +    // This function started out as an optimized version of code found in Tim Cameron Ryan's IERange
          +    // (http://code.google.com/p/ierange/)
          +    function createBoundaryTextRange(boundaryPosition, isStart) {
          +        var boundaryNode, boundaryParent, boundaryOffset = boundaryPosition.offset;
          +        var doc = dom.getDocument(boundaryPosition.node);
          +        var workingNode, childNodes, workingRange = doc.body.createTextRange();
          +        var nodeIsDataNode = dom.isCharacterDataNode(boundaryPosition.node);
          +
          +        if (nodeIsDataNode) {
          +            boundaryNode = boundaryPosition.node;
          +            boundaryParent = boundaryNode.parentNode;
          +        } else {
          +            childNodes = boundaryPosition.node.childNodes;
          +            boundaryNode = (boundaryOffset < childNodes.length) ? childNodes[boundaryOffset] : null;
          +            boundaryParent = boundaryPosition.node;
          +        }
          +
          +        // Position the range immediately before the node containing the boundary
          +        workingNode = doc.createElement("span");
          +
          +        // Making the working element non-empty element persuades IE to consider the TextRange boundary to be within the
          +        // element rather than immediately before or after it, which is what we want
          +        workingNode.innerHTML = "&#feff;";
          +
          +        // insertBefore is supposed to work like appendChild if the second parameter is null. However, a bug report
          +        // for IERange suggests that it can crash the browser: http://code.google.com/p/ierange/issues/detail?id=12
          +        if (boundaryNode) {
          +            boundaryParent.insertBefore(workingNode, boundaryNode);
          +        } else {
          +            boundaryParent.appendChild(workingNode);
          +        }
          +
          +        workingRange.moveToElementText(workingNode);
          +        workingRange.collapse(!isStart);
          +
          +        // Clean up
          +        boundaryParent.removeChild(workingNode);
          +
          +        // Move the working range to the text offset, if required
          +        if (nodeIsDataNode) {
          +            workingRange[isStart ? "moveStart" : "moveEnd"]("character", boundaryOffset);
          +        }
          +
          +        return workingRange;
          +    }
          +
          +    /*----------------------------------------------------------------------------------------------------------------*/
          +
          +    if (api.features.implementsDomRange && (!api.features.implementsTextRange || !api.config.preferTextRange)) {
          +        // This is a wrapper around the browser's native DOM Range. It has two aims:
          +        // - Provide workarounds for specific browser bugs
          +        // - provide convenient extensions, which are inherited from Rangy's DomRange
          +
          +        (function() {
          +            var rangeProto;
          +            var rangeProperties = DomRange.rangeProperties;
          +            var canSetRangeStartAfterEnd;
          +
          +            function updateRangeProperties(range) {
          +                var i = rangeProperties.length, prop;
          +                while (i--) {
          +                    prop = rangeProperties[i];
          +                    range[prop] = range.nativeRange[prop];
          +                }
          +            }
          +
          +            function updateNativeRange(range, startContainer, startOffset, endContainer,endOffset) {
          +                var startMoved = (range.startContainer !== startContainer || range.startOffset != startOffset);
          +                var endMoved = (range.endContainer !== endContainer || range.endOffset != endOffset);
          +
          +                // Always set both boundaries for the benefit of IE9 (see issue 35)
          +                if (startMoved || endMoved) {
          +                    range.setEnd(endContainer, endOffset);
          +                    range.setStart(startContainer, startOffset);
          +                }
          +            }
          +
          +            function detach(range) {
          +                range.nativeRange.detach();
          +                range.detached = true;
          +                var i = rangeProperties.length, prop;
          +                while (i--) {
          +                    prop = rangeProperties[i];
          +                    range[prop] = null;
          +                }
          +            }
          +
          +            var createBeforeAfterNodeSetter;
          +
          +            WrappedRange = function(range) {
          +                if (!range) {
          +                    throw new Error("Range must be specified");
          +                }
          +                this.nativeRange = range;
          +                updateRangeProperties(this);
          +            };
          +
          +            DomRange.createPrototypeRange(WrappedRange, updateNativeRange, detach);
          +
          +            rangeProto = WrappedRange.prototype;
          +
          +            rangeProto.selectNode = function(node) {
          +                this.nativeRange.selectNode(node);
          +                updateRangeProperties(this);
          +            };
          +
          +            rangeProto.deleteContents = function() {
          +                this.nativeRange.deleteContents();
          +                updateRangeProperties(this);
          +            };
          +
          +            rangeProto.extractContents = function() {
          +                var frag = this.nativeRange.extractContents();
          +                updateRangeProperties(this);
          +                return frag;
          +            };
          +
          +            rangeProto.cloneContents = function() {
          +                return this.nativeRange.cloneContents();
          +            };
          +
          +            // TODO: Until I can find a way to programmatically trigger the Firefox bug (apparently long-standing, still
          +            // present in 3.6.8) that throws "Index or size is negative or greater than the allowed amount" for
          +            // insertNode in some circumstances, all browsers will have to use the Rangy's own implementation of
          +            // insertNode, which works but is almost certainly slower than the native implementation.
          +/*
          +            rangeProto.insertNode = function(node) {
          +                this.nativeRange.insertNode(node);
          +                updateRangeProperties(this);
          +            };
          +*/
          +
          +            rangeProto.surroundContents = function(node) {
          +                this.nativeRange.surroundContents(node);
          +                updateRangeProperties(this);
          +            };
          +
          +            rangeProto.collapse = function(isStart) {
          +                this.nativeRange.collapse(isStart);
          +                updateRangeProperties(this);
          +            };
          +
          +            rangeProto.cloneRange = function() {
          +                return new WrappedRange(this.nativeRange.cloneRange());
          +            };
          +
          +            rangeProto.refresh = function() {
          +                updateRangeProperties(this);
          +            };
          +
          +            rangeProto.toString = function() {
          +                return this.nativeRange.toString();
          +            };
          +
          +            // Create test range and node for feature detection
          +
          +            var testTextNode = document.createTextNode("test");
          +            dom.getBody(document).appendChild(testTextNode);
          +            var range = document.createRange();
          +
          +            /*--------------------------------------------------------------------------------------------------------*/
          +
          +            // Test for Firefox 2 bug that prevents moving the start of a Range to a point after its current end and
          +            // correct for it
          +
          +            range.setStart(testTextNode, 0);
          +            range.setEnd(testTextNode, 0);
          +
          +            try {
          +                range.setStart(testTextNode, 1);
          +                canSetRangeStartAfterEnd = true;
          +
          +                rangeProto.setStart = function(node, offset) {
          +                    this.nativeRange.setStart(node, offset);
          +                    updateRangeProperties(this);
          +                };
          +
          +                rangeProto.setEnd = function(node, offset) {
          +                    this.nativeRange.setEnd(node, offset);
          +                    updateRangeProperties(this);
          +                };
          +
          +                createBeforeAfterNodeSetter = function(name) {
          +                    return function(node) {
          +                        this.nativeRange[name](node);
          +                        updateRangeProperties(this);
          +                    };
          +                };
          +
          +            } catch(ex) {
          +
          +
          +                canSetRangeStartAfterEnd = false;
          +
          +                rangeProto.setStart = function(node, offset) {
          +                    try {
          +                        this.nativeRange.setStart(node, offset);
          +                    } catch (ex) {
          +                        this.nativeRange.setEnd(node, offset);
          +                        this.nativeRange.setStart(node, offset);
          +                    }
          +                    updateRangeProperties(this);
          +                };
          +
          +                rangeProto.setEnd = function(node, offset) {
          +                    try {
          +                        this.nativeRange.setEnd(node, offset);
          +                    } catch (ex) {
          +                        this.nativeRange.setStart(node, offset);
          +                        this.nativeRange.setEnd(node, offset);
          +                    }
          +                    updateRangeProperties(this);
          +                };
          +
          +                createBeforeAfterNodeSetter = function(name, oppositeName) {
          +                    return function(node) {
          +                        try {
          +                            this.nativeRange[name](node);
          +                        } catch (ex) {
          +                            this.nativeRange[oppositeName](node);
          +                            this.nativeRange[name](node);
          +                        }
          +                        updateRangeProperties(this);
          +                    };
          +                };
          +            }
          +
          +            rangeProto.setStartBefore = createBeforeAfterNodeSetter("setStartBefore", "setEndBefore");
          +            rangeProto.setStartAfter = createBeforeAfterNodeSetter("setStartAfter", "setEndAfter");
          +            rangeProto.setEndBefore = createBeforeAfterNodeSetter("setEndBefore", "setStartBefore");
          +            rangeProto.setEndAfter = createBeforeAfterNodeSetter("setEndAfter", "setStartAfter");
          +
          +            /*--------------------------------------------------------------------------------------------------------*/
          +
          +            // Test for and correct Firefox 2 behaviour with selectNodeContents on text nodes: it collapses the range to
          +            // the 0th character of the text node
          +            range.selectNodeContents(testTextNode);
          +            if (range.startContainer == testTextNode && range.endContainer == testTextNode &&
          +                    range.startOffset == 0 && range.endOffset == testTextNode.length) {
          +                rangeProto.selectNodeContents = function(node) {
          +                    this.nativeRange.selectNodeContents(node);
          +                    updateRangeProperties(this);
          +                };
          +            } else {
          +                rangeProto.selectNodeContents = function(node) {
          +                    this.setStart(node, 0);
          +                    this.setEnd(node, DomRange.getEndOffset(node));
          +                };
          +            }
          +
          +            /*--------------------------------------------------------------------------------------------------------*/
          +
          +            // Test for WebKit bug that has the beahviour of compareBoundaryPoints round the wrong way for constants
          +            // START_TO_END and END_TO_START: https://bugs.webkit.org/show_bug.cgi?id=20738
          +
          +            range.selectNodeContents(testTextNode);
          +            range.setEnd(testTextNode, 3);
          +
          +            var range2 = document.createRange();
          +            range2.selectNodeContents(testTextNode);
          +            range2.setEnd(testTextNode, 4);
          +            range2.setStart(testTextNode, 2);
          +
          +            if (range.compareBoundaryPoints(range.START_TO_END, range2) == -1 &
          +                    range.compareBoundaryPoints(range.END_TO_START, range2) == 1) {
          +                // This is the wrong way round, so correct for it
          +
          +
          +                rangeProto.compareBoundaryPoints = function(type, range) {
          +                    range = range.nativeRange || range;
          +                    if (type == range.START_TO_END) {
          +                        type = range.END_TO_START;
          +                    } else if (type == range.END_TO_START) {
          +                        type = range.START_TO_END;
          +                    }
          +                    return this.nativeRange.compareBoundaryPoints(type, range);
          +                };
          +            } else {
          +                rangeProto.compareBoundaryPoints = function(type, range) {
          +                    return this.nativeRange.compareBoundaryPoints(type, range.nativeRange || range);
          +                };
          +            }
          +
          +            /*--------------------------------------------------------------------------------------------------------*/
          +
          +            // Test for existence of createContextualFragment and delegate to it if it exists
          +            if (api.util.isHostMethod(range, "createContextualFragment")) {
          +                rangeProto.createContextualFragment = function(fragmentStr) {
          +                    return this.nativeRange.createContextualFragment(fragmentStr);
          +                };
          +            }
          +
          +            /*--------------------------------------------------------------------------------------------------------*/
          +
          +            // Clean up
          +            dom.getBody(document).removeChild(testTextNode);
          +            range.detach();
          +            range2.detach();
          +        })();
          +
          +        api.createNativeRange = function(doc) {
          +            doc = doc || document;
          +            return doc.createRange();
          +        };
          +    } else if (api.features.implementsTextRange) {
          +        // This is a wrapper around a TextRange, providing full DOM Range functionality using rangy's DomRange as a
          +        // prototype
          +
          +        WrappedRange = function(textRange) {
          +            this.textRange = textRange;
          +            this.refresh();
          +        };
          +
          +        WrappedRange.prototype = new DomRange(document);
          +
          +        WrappedRange.prototype.refresh = function() {
          +            var start, end;
          +
          +            // TextRange's parentElement() method cannot be trusted. getTextRangeContainerElement() works around that.
          +            var rangeContainerElement = getTextRangeContainerElement(this.textRange);
          +
          +            if (textRangeIsCollapsed(this.textRange)) {
          +                end = start = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, true, true);
          +            } else {
          +
          +                start = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, true, false);
          +                end = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, false, false);
          +            }
          +
          +            this.setStart(start.node, start.offset);
          +            this.setEnd(end.node, end.offset);
          +        };
          +
          +        DomRange.copyComparisonConstants(WrappedRange);
          +
          +        // Add WrappedRange as the Range property of the global object to allow expression like Range.END_TO_END to work
          +        var globalObj = (function() { return this; })();
          +        if (typeof globalObj.Range == "undefined") {
          +            globalObj.Range = WrappedRange;
          +        }
          +
          +        api.createNativeRange = function(doc) {
          +            doc = doc || document;
          +            return doc.body.createTextRange();
          +        };
          +    }
          +
          +    if (api.features.implementsTextRange) {
          +        WrappedRange.rangeToTextRange = function(range) {
          +            if (range.collapsed) {
          +                var tr = createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
          +
          +
          +
          +                return tr;
          +
          +                //return createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
          +            } else {
          +                var startRange = createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
          +                var endRange = createBoundaryTextRange(new DomPosition(range.endContainer, range.endOffset), false);
          +                var textRange = dom.getDocument(range.startContainer).body.createTextRange();
          +                textRange.setEndPoint("StartToStart", startRange);
          +                textRange.setEndPoint("EndToEnd", endRange);
          +                return textRange;
          +            }
          +        };
          +    }
          +
          +    WrappedRange.prototype.getName = function() {
          +        return "WrappedRange";
          +    };
          +
          +    api.WrappedRange = WrappedRange;
          +
          +    api.createRange = function(doc) {
          +        doc = doc || document;
          +        return new WrappedRange(api.createNativeRange(doc));
          +    };
          +
          +    api.createRangyRange = function(doc) {
          +        doc = doc || document;
          +        return new DomRange(doc);
          +    };
          +
          +    api.createIframeRange = function(iframeEl) {
          +        return api.createRange(dom.getIframeDocument(iframeEl));
          +    };
          +
          +    api.createIframeRangyRange = function(iframeEl) {
          +        return api.createRangyRange(dom.getIframeDocument(iframeEl));
          +    };
          +
          +    api.addCreateMissingNativeApiListener(function(win) {
          +        var doc = win.document;
          +        if (typeof doc.createRange == "undefined") {
          +            doc.createRange = function() {
          +                return api.createRange(this);
          +            };
          +        }
          +        doc = win = null;
          +    });
          +});rangy.createModule("WrappedSelection", function(api, module) {
          +    // This will create a selection object wrapper that follows the Selection object found in the WHATWG draft DOM Range
          +    // spec (http://html5.org/specs/dom-range.html)
          +
          +    api.requireModules( ["DomUtil", "DomRange", "WrappedRange"] );
          +
          +    api.config.checkSelectionRanges = true;
          +
          +    var BOOLEAN = "boolean",
          +        windowPropertyName = "_rangySelection",
          +        dom = api.dom,
          +        util = api.util,
          +        DomRange = api.DomRange,
          +        WrappedRange = api.WrappedRange,
          +        DOMException = api.DOMException,
          +        DomPosition = dom.DomPosition,
          +        getSelection,
          +        selectionIsCollapsed,
          +        CONTROL = "Control";
          +
          +
          +
          +    function getWinSelection(winParam) {
          +        return (winParam || window).getSelection();
          +    }
          +
          +    function getDocSelection(winParam) {
          +        return (winParam || window).document.selection;
          +    }
          +
          +    // Test for the Range/TextRange and Selection features required
          +    // Test for ability to retrieve selection
          +    var implementsWinGetSelection = api.util.isHostMethod(window, "getSelection"),
          +        implementsDocSelection = api.util.isHostObject(document, "selection");
          +
          +    var useDocumentSelection = implementsDocSelection && (!implementsWinGetSelection || api.config.preferTextRange);
          +
          +    if (useDocumentSelection) {
          +        getSelection = getDocSelection;
          +        api.isSelectionValid = function(winParam) {
          +            var doc = (winParam || window).document, nativeSel = doc.selection;
          +
          +            // Check whether the selection TextRange is actually contained within the correct document
          +            return (nativeSel.type != "None" || dom.getDocument(nativeSel.createRange().parentElement()) == doc);
          +        };
          +    } else if (implementsWinGetSelection) {
          +        getSelection = getWinSelection;
          +        api.isSelectionValid = function() {
          +            return true;
          +        };
          +    } else {
          +        module.fail("Neither document.selection or window.getSelection() detected.");
          +    }
          +
          +    api.getNativeSelection = getSelection;
          +
          +    var testSelection = getSelection();
          +    var testRange = api.createNativeRange(document);
          +    var body = dom.getBody(document);
          +
          +    // Obtaining a range from a selection
          +    var selectionHasAnchorAndFocus = util.areHostObjects(testSelection, ["anchorNode", "focusNode"] &&
          +                                     util.areHostProperties(testSelection, ["anchorOffset", "focusOffset"]));
          +    api.features.selectionHasAnchorAndFocus = selectionHasAnchorAndFocus;
          +
          +    // Test for existence of native selection extend() method
          +    var selectionHasExtend = util.isHostMethod(testSelection, "extend");
          +    api.features.selectionHasExtend = selectionHasExtend;
          +
          +    // Test if rangeCount exists
          +    var selectionHasRangeCount = (typeof testSelection.rangeCount == "number");
          +    api.features.selectionHasRangeCount = selectionHasRangeCount;
          +
          +    var selectionSupportsMultipleRanges = false;
          +    var collapsedNonEditableSelectionsSupported = true;
          +
          +    if (util.areHostMethods(testSelection, ["addRange", "getRangeAt", "removeAllRanges"]) &&
          +            typeof testSelection.rangeCount == "number" && api.features.implementsDomRange) {
          +
          +        (function() {
          +            var iframe = document.createElement("iframe");
          +            body.appendChild(iframe);
          +
          +            var iframeDoc = dom.getIframeDocument(iframe);
          +            iframeDoc.open();
          +            iframeDoc.write("12");
          +            iframeDoc.close();
          +
          +            var sel = dom.getIframeWindow(iframe).getSelection();
          +            var docEl = iframeDoc.documentElement;
          +            var iframeBody = docEl.lastChild, textNode = iframeBody.firstChild;
          +
          +            // Test whether the native selection will allow a collapsed selection within a non-editable element
          +            var r1 = iframeDoc.createRange();
          +            r1.setStart(textNode, 1);
          +            r1.collapse(true);
          +            sel.addRange(r1);
          +            collapsedNonEditableSelectionsSupported = (sel.rangeCount == 1);
          +            sel.removeAllRanges();
          +
          +            // Test whether the native selection is capable of supporting multiple ranges
          +            var r2 = r1.cloneRange();
          +            r1.setStart(textNode, 0);
          +            r2.setEnd(textNode, 2);
          +            sel.addRange(r1);
          +            sel.addRange(r2);
          +
          +            selectionSupportsMultipleRanges = (sel.rangeCount == 2);
          +
          +            // Clean up
          +            r1.detach();
          +            r2.detach();
          +
          +            body.removeChild(iframe);
          +        })();
          +    }
          +
          +    api.features.selectionSupportsMultipleRanges = selectionSupportsMultipleRanges;
          +    api.features.collapsedNonEditableSelectionsSupported = collapsedNonEditableSelectionsSupported;
          +
          +    // ControlRanges
          +    var implementsControlRange = false, testControlRange;
          +
          +    if (body && util.isHostMethod(body, "createControlRange")) {
          +        testControlRange = body.createControlRange();
          +        if (util.areHostProperties(testControlRange, ["item", "add"])) {
          +            implementsControlRange = true;
          +        }
          +    }
          +    api.features.implementsControlRange = implementsControlRange;
          +
          +    // Selection collapsedness
          +    if (selectionHasAnchorAndFocus) {
          +        selectionIsCollapsed = function(sel) {
          +            return sel.anchorNode === sel.focusNode && sel.anchorOffset === sel.focusOffset;
          +        };
          +    } else {
          +        selectionIsCollapsed = function(sel) {
          +            return sel.rangeCount ? sel.getRangeAt(sel.rangeCount - 1).collapsed : false;
          +        };
          +    }
          +
          +    function updateAnchorAndFocusFromRange(sel, range, backwards) {
          +        var anchorPrefix = backwards ? "end" : "start", focusPrefix = backwards ? "start" : "end";
          +        sel.anchorNode = range[anchorPrefix + "Container"];
          +        sel.anchorOffset = range[anchorPrefix + "Offset"];
          +        sel.focusNode = range[focusPrefix + "Container"];
          +        sel.focusOffset = range[focusPrefix + "Offset"];
          +    }
          +
          +    function updateAnchorAndFocusFromNativeSelection(sel) {
          +        var nativeSel = sel.nativeSelection;
          +        sel.anchorNode = nativeSel.anchorNode;
          +        sel.anchorOffset = nativeSel.anchorOffset;
          +        sel.focusNode = nativeSel.focusNode;
          +        sel.focusOffset = nativeSel.focusOffset;
          +    }
          +
          +    function updateEmptySelection(sel) {
          +        sel.anchorNode = sel.focusNode = null;
          +        sel.anchorOffset = sel.focusOffset = 0;
          +        sel.rangeCount = 0;
          +        sel.isCollapsed = true;
          +        sel._ranges.length = 0;
          +    }
          +
          +    function getNativeRange(range) {
          +        var nativeRange;
          +        if (range instanceof DomRange) {
          +            nativeRange = range._selectionNativeRange;
          +            if (!nativeRange) {
          +                nativeRange = api.createNativeRange(dom.getDocument(range.startContainer));
          +                nativeRange.setEnd(range.endContainer, range.endOffset);
          +                nativeRange.setStart(range.startContainer, range.startOffset);
          +                range._selectionNativeRange = nativeRange;
          +                range.attachListener("detach", function() {
          +
          +                    this._selectionNativeRange = null;
          +                });
          +            }
          +        } else if (range instanceof WrappedRange) {
          +            nativeRange = range.nativeRange;
          +        } else if (api.features.implementsDomRange && (range instanceof dom.getWindow(range.startContainer).Range)) {
          +            nativeRange = range;
          +        }
          +        return nativeRange;
          +    }
          +
          +    function rangeContainsSingleElement(rangeNodes) {
          +        if (!rangeNodes.length || rangeNodes[0].nodeType != 1) {
          +            return false;
          +        }
          +        for (var i = 1, len = rangeNodes.length; i < len; ++i) {
          +            if (!dom.isAncestorOf(rangeNodes[0], rangeNodes[i])) {
          +                return false;
          +            }
          +        }
          +        return true;
          +    }
          +
          +    function getSingleElementFromRange(range) {
          +        var nodes = range.getNodes();
          +        if (!rangeContainsSingleElement(nodes)) {
          +            throw new Error("getSingleElementFromRange: range " + range.inspect() + " did not consist of a single element");
          +        }
          +        return nodes[0];
          +    }
          +
          +    function isTextRange(range) {
          +        return !!range && typeof range.text != "undefined";
          +    }
          +
          +    function updateFromTextRange(sel, range) {
          +        // Create a Range from the selected TextRange
          +        var wrappedRange = new WrappedRange(range);
          +        sel._ranges = [wrappedRange];
          +
          +        updateAnchorAndFocusFromRange(sel, wrappedRange, false);
          +        sel.rangeCount = 1;
          +        sel.isCollapsed = wrappedRange.collapsed;
          +    }
          +
          +    function updateControlSelection(sel) {
          +        // Update the wrapped selection based on what's now in the native selection
          +        sel._ranges.length = 0;
          +        if (sel.docSelection.type == "None") {
          +            updateEmptySelection(sel);
          +        } else {
          +            var controlRange = sel.docSelection.createRange();
          +            if (isTextRange(controlRange)) {
          +                // This case (where the selection type is "Control" and calling createRange() on the selection returns
          +                // a TextRange) can happen in IE 9. It happens, for example, when all elements in the selected
          +                // ControlRange have been removed from the ControlRange and removed from the document.
          +                updateFromTextRange(sel, controlRange);
          +            } else {
          +                sel.rangeCount = controlRange.length;
          +                var range, doc = dom.getDocument(controlRange.item(0));
          +                for (var i = 0; i < sel.rangeCount; ++i) {
          +                    range = api.createRange(doc);
          +                    range.selectNode(controlRange.item(i));
          +                    sel._ranges.push(range);
          +                }
          +                sel.isCollapsed = sel.rangeCount == 1 && sel._ranges[0].collapsed;
          +                updateAnchorAndFocusFromRange(sel, sel._ranges[sel.rangeCount - 1], false);
          +            }
          +        }
          +    }
          +
          +    function addRangeToControlSelection(sel, range) {
          +        var controlRange = sel.docSelection.createRange();
          +        var rangeElement = getSingleElementFromRange(range);
          +
          +        // Create a new ControlRange containing all the elements in the selected ControlRange plus the element
          +        // contained by the supplied range
          +        var doc = dom.getDocument(controlRange.item(0));
          +        var newControlRange = dom.getBody(doc).createControlRange();
          +        for (var i = 0, len = controlRange.length; i < len; ++i) {
          +            newControlRange.add(controlRange.item(i));
          +        }
          +        try {
          +            newControlRange.add(rangeElement);
          +        } catch (ex) {
          +            throw new Error("addRange(): Element within the specified Range could not be added to control selection (does it have layout?)");
          +        }
          +        newControlRange.select();
          +
          +        // Update the wrapped selection based on what's now in the native selection
          +        updateControlSelection(sel);
          +    }
          +
          +    var getSelectionRangeAt;
          +
          +    if (util.isHostMethod(testSelection,  "getRangeAt")) {
          +        getSelectionRangeAt = function(sel, index) {
          +            try {
          +                return sel.getRangeAt(index);
          +            } catch(ex) {
          +                return null;
          +            }
          +        };
          +    } else if (selectionHasAnchorAndFocus) {
          +        getSelectionRangeAt = function(sel) {
          +            var doc = dom.getDocument(sel.anchorNode);
          +            var range = api.createRange(doc);
          +            range.setStart(sel.anchorNode, sel.anchorOffset);
          +            range.setEnd(sel.focusNode, sel.focusOffset);
          +
          +            // Handle the case when the selection was selected backwards (from the end to the start in the
          +            // document)
          +            if (range.collapsed !== this.isCollapsed) {
          +                range.setStart(sel.focusNode, sel.focusOffset);
          +                range.setEnd(sel.anchorNode, sel.anchorOffset);
          +            }
          +
          +            return range;
          +        };
          +    }
          +
          +    /**
          +     * @constructor
          +     */
          +    function WrappedSelection(selection, docSelection, win) {
          +        this.nativeSelection = selection;
          +        this.docSelection = docSelection;
          +        this._ranges = [];
          +        this.win = win;
          +        this.refresh();
          +    }
          +
          +    api.getSelection = function(win) {
          +        win = win || window;
          +        var sel = win[windowPropertyName];
          +        var nativeSel = getSelection(win), docSel = implementsDocSelection ? getDocSelection(win) : null;
          +        if (sel) {
          +            sel.nativeSelection = nativeSel;
          +            sel.docSelection = docSel;
          +            sel.refresh(win);
          +        } else {
          +            sel = new WrappedSelection(nativeSel, docSel, win);
          +            win[windowPropertyName] = sel;
          +        }
          +        return sel;
          +    };
          +
          +    api.getIframeSelection = function(iframeEl) {
          +        return api.getSelection(dom.getIframeWindow(iframeEl));
          +    };
          +
          +    var selProto = WrappedSelection.prototype;
          +
          +    function createControlSelection(sel, ranges) {
          +        // Ensure that the selection becomes of type "Control"
          +        var doc = dom.getDocument(ranges[0].startContainer);
          +        var controlRange = dom.getBody(doc).createControlRange();
          +        for (var i = 0, el; i < rangeCount; ++i) {
          +            el = getSingleElementFromRange(ranges[i]);
          +            try {
          +                controlRange.add(el);
          +            } catch (ex) {
          +                throw new Error("setRanges(): Element within the one of the specified Ranges could not be added to control selection (does it have layout?)");
          +            }
          +        }
          +        controlRange.select();
          +
          +        // Update the wrapped selection based on what's now in the native selection
          +        updateControlSelection(sel);
          +    }
          +
          +    // Selecting a range
          +    if (!useDocumentSelection && selectionHasAnchorAndFocus && util.areHostMethods(testSelection, ["removeAllRanges", "addRange"])) {
          +        selProto.removeAllRanges = function() {
          +            this.nativeSelection.removeAllRanges();
          +            updateEmptySelection(this);
          +        };
          +
          +        var addRangeBackwards = function(sel, range) {
          +            var doc = DomRange.getRangeDocument(range);
          +            var endRange = api.createRange(doc);
          +            endRange.collapseToPoint(range.endContainer, range.endOffset);
          +            sel.nativeSelection.addRange(getNativeRange(endRange));
          +            sel.nativeSelection.extend(range.startContainer, range.startOffset);
          +            sel.refresh();
          +        };
          +
          +        if (selectionHasRangeCount) {
          +            selProto.addRange = function(range, backwards) {
          +                if (implementsControlRange && implementsDocSelection && this.docSelection.type == CONTROL) {
          +                    addRangeToControlSelection(this, range);
          +                } else {
          +                    if (backwards && selectionHasExtend) {
          +                        addRangeBackwards(this, range);
          +                    } else {
          +                        var previousRangeCount;
          +                        if (selectionSupportsMultipleRanges) {
          +                            previousRangeCount = this.rangeCount;
          +                        } else {
          +                            this.removeAllRanges();
          +                            previousRangeCount = 0;
          +                        }
          +                        this.nativeSelection.addRange(getNativeRange(range));
          +
          +                        // Check whether adding the range was successful
          +                        this.rangeCount = this.nativeSelection.rangeCount;
          +
          +                        if (this.rangeCount == previousRangeCount + 1) {
          +                            // The range was added successfully
          +
          +                            // Check whether the range that we added to the selection is reflected in the last range extracted from
          +                            // the selection
          +                            if (api.config.checkSelectionRanges) {
          +                                var nativeRange = getSelectionRangeAt(this.nativeSelection, this.rangeCount - 1);
          +                                if (nativeRange && !DomRange.rangesEqual(nativeRange, range)) {
          +                                    // Happens in WebKit with, for example, a selection placed at the start of a text node
          +                                    range = new WrappedRange(nativeRange);
          +                                }
          +                            }
          +                            this._ranges[this.rangeCount - 1] = range;
          +                            updateAnchorAndFocusFromRange(this, range, selectionIsBackwards(this.nativeSelection));
          +                            this.isCollapsed = selectionIsCollapsed(this);
          +                        } else {
          +                            // The range was not added successfully. The simplest thing is to refresh
          +                            this.refresh();
          +                        }
          +                    }
          +                }
          +            };
          +        } else {
          +            selProto.addRange = function(range, backwards) {
          +                if (backwards && selectionHasExtend) {
          +                    addRangeBackwards(this, range);
          +                } else {
          +                    this.nativeSelection.addRange(getNativeRange(range));
          +                    this.refresh();
          +                }
          +            };
          +        }
          +
          +        selProto.setRanges = function(ranges) {
          +            if (implementsControlRange && ranges.length > 1) {
          +                createControlSelection(this, ranges);
          +            } else {
          +                this.removeAllRanges();
          +                for (var i = 0, len = ranges.length; i < len; ++i) {
          +                    this.addRange(ranges[i]);
          +                }
          +            }
          +        };
          +    } else if (util.isHostMethod(testSelection, "empty") && util.isHostMethod(testRange, "select") &&
          +               implementsControlRange && useDocumentSelection) {
          +
          +        selProto.removeAllRanges = function() {
          +            // Added try/catch as fix for issue #21
          +            try {
          +                this.docSelection.empty();
          +
          +                // Check for empty() not working (issue #24)
          +                if (this.docSelection.type != "None") {
          +                    // Work around failure to empty a control selection by instead selecting a TextRange and then
          +                    // calling empty()
          +                    var doc;
          +                    if (this.anchorNode) {
          +                        doc = dom.getDocument(this.anchorNode);
          +                    } else if (this.docSelection.type == CONTROL) {
          +                        var controlRange = this.docSelection.createRange();
          +                        if (controlRange.length) {
          +                            doc = dom.getDocument(controlRange.item(0)).body.createTextRange();
          +                        }
          +                    }
          +                    if (doc) {
          +                        var textRange = doc.body.createTextRange();
          +                        textRange.select();
          +                        this.docSelection.empty();
          +                    }
          +                }
          +            } catch(ex) {}
          +            updateEmptySelection(this);
          +        };
          +
          +        selProto.addRange = function(range) {
          +            if (this.docSelection.type == CONTROL) {
          +                addRangeToControlSelection(this, range);
          +            } else {
          +                WrappedRange.rangeToTextRange(range).select();
          +                this._ranges[0] = range;
          +                this.rangeCount = 1;
          +                this.isCollapsed = this._ranges[0].collapsed;
          +                updateAnchorAndFocusFromRange(this, range, false);
          +            }
          +        };
          +
          +        selProto.setRanges = function(ranges) {
          +            this.removeAllRanges();
          +            var rangeCount = ranges.length;
          +            if (rangeCount > 1) {
          +                createControlSelection(this, ranges);
          +            } else if (rangeCount) {
          +                this.addRange(ranges[0]);
          +            }
          +        };
          +    } else {
          +        module.fail("No means of selecting a Range or TextRange was found");
          +        return false;
          +    }
          +
          +    selProto.getRangeAt = function(index) {
          +        if (index < 0 || index >= this.rangeCount) {
          +            throw new DOMException("INDEX_SIZE_ERR");
          +        } else {
          +            return this._ranges[index];
          +        }
          +    };
          +
          +    var refreshSelection;
          +
          +    if (useDocumentSelection) {
          +        refreshSelection = function(sel) {
          +            var range;
          +            if (api.isSelectionValid(sel.win)) {
          +                range = sel.docSelection.createRange();
          +            } else {
          +                range = dom.getBody(sel.win.document).createTextRange();
          +                range.collapse(true);
          +            }
          +
          +
          +            if (sel.docSelection.type == CONTROL) {
          +                updateControlSelection(sel);
          +            } else if (isTextRange(range)) {
          +                updateFromTextRange(sel, range);
          +            } else {
          +                updateEmptySelection(sel);
          +            }
          +        };
          +    } else if (util.isHostMethod(testSelection, "getRangeAt") && typeof testSelection.rangeCount == "number") {
          +        refreshSelection = function(sel) {
          +            if (implementsControlRange && implementsDocSelection && sel.docSelection.type == CONTROL) {
          +                updateControlSelection(sel);
          +            } else {
          +                sel._ranges.length = sel.rangeCount = sel.nativeSelection.rangeCount;
          +                if (sel.rangeCount) {
          +                    for (var i = 0, len = sel.rangeCount; i < len; ++i) {
          +                        sel._ranges[i] = new api.WrappedRange(sel.nativeSelection.getRangeAt(i));
          +                    }
          +                    updateAnchorAndFocusFromRange(sel, sel._ranges[sel.rangeCount - 1], selectionIsBackwards(sel.nativeSelection));
          +                    sel.isCollapsed = selectionIsCollapsed(sel);
          +                } else {
          +                    updateEmptySelection(sel);
          +                }
          +            }
          +        };
          +    } else if (selectionHasAnchorAndFocus && typeof testSelection.isCollapsed == BOOLEAN && typeof testRange.collapsed == BOOLEAN && api.features.implementsDomRange) {
          +        refreshSelection = function(sel) {
          +            var range, nativeSel = sel.nativeSelection;
          +            if (nativeSel.anchorNode) {
          +                range = getSelectionRangeAt(nativeSel, 0);
          +                sel._ranges = [range];
          +                sel.rangeCount = 1;
          +                updateAnchorAndFocusFromNativeSelection(sel);
          +                sel.isCollapsed = selectionIsCollapsed(sel);
          +            } else {
          +                updateEmptySelection(sel);
          +            }
          +        };
          +    } else {
          +        module.fail("No means of obtaining a Range or TextRange from the user's selection was found");
          +        return false;
          +    }
          +
          +    selProto.refresh = function(checkForChanges) {
          +        var oldRanges = checkForChanges ? this._ranges.slice(0) : null;
          +        refreshSelection(this);
          +        if (checkForChanges) {
          +            var i = oldRanges.length;
          +            if (i != this._ranges.length) {
          +                return false;
          +            }
          +            while (i--) {
          +                if (!DomRange.rangesEqual(oldRanges[i], this._ranges[i])) {
          +                    return false;
          +                }
          +            }
          +            return true;
          +        }
          +    };
          +
          +    // Removal of a single range
          +    var removeRangeManually = function(sel, range) {
          +        var ranges = sel.getAllRanges(), removed = false;
          +        sel.removeAllRanges();
          +        for (var i = 0, len = ranges.length; i < len; ++i) {
          +            if (removed || range !== ranges[i]) {
          +                sel.addRange(ranges[i]);
          +            } else {
          +                // According to the draft WHATWG Range spec, the same range may be added to the selection multiple
          +                // times. removeRange should only remove the first instance, so the following ensures only the first
          +                // instance is removed
          +                removed = true;
          +            }
          +        }
          +        if (!sel.rangeCount) {
          +            updateEmptySelection(sel);
          +        }
          +    };
          +
          +    if (implementsControlRange) {
          +        selProto.removeRange = function(range) {
          +            if (this.docSelection.type == CONTROL) {
          +                var controlRange = this.docSelection.createRange();
          +                var rangeElement = getSingleElementFromRange(range);
          +
          +                // Create a new ControlRange containing all the elements in the selected ControlRange minus the
          +                // element contained by the supplied range
          +                var doc = dom.getDocument(controlRange.item(0));
          +                var newControlRange = dom.getBody(doc).createControlRange();
          +                var el, removed = false;
          +                for (var i = 0, len = controlRange.length; i < len; ++i) {
          +                    el = controlRange.item(i);
          +                    if (el !== rangeElement || removed) {
          +                        newControlRange.add(controlRange.item(i));
          +                    } else {
          +                        removed = true;
          +                    }
          +                }
          +                newControlRange.select();
          +
          +                // Update the wrapped selection based on what's now in the native selection
          +                updateControlSelection(this);
          +            } else {
          +                removeRangeManually(this, range);
          +            }
          +        };
          +    } else {
          +        selProto.removeRange = function(range) {
          +            removeRangeManually(this, range);
          +        };
          +    }
          +
          +    // Detecting if a selection is backwards
          +    var selectionIsBackwards;
          +    if (!useDocumentSelection && selectionHasAnchorAndFocus && api.features.implementsDomRange) {
          +        selectionIsBackwards = function(sel) {
          +            var backwards = false;
          +            if (sel.anchorNode) {
          +                backwards = (dom.comparePoints(sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset) == 1);
          +            }
          +            return backwards;
          +        };
          +
          +        selProto.isBackwards = function() {
          +            return selectionIsBackwards(this);
          +        };
          +    } else {
          +        selectionIsBackwards = selProto.isBackwards = function() {
          +            return false;
          +        };
          +    }
          +
          +    // Selection text
          +    // This is conformant to the new WHATWG DOM Range draft spec but differs from WebKit and Mozilla's implementation
          +    selProto.toString = function() {
          +
          +        var rangeTexts = [];
          +        for (var i = 0, len = this.rangeCount; i < len; ++i) {
          +            rangeTexts[i] = "" + this._ranges[i];
          +        }
          +        return rangeTexts.join("");
          +    };
          +
          +    function assertNodeInSameDocument(sel, node) {
          +        if (sel.anchorNode && (dom.getDocument(sel.anchorNode) !== dom.getDocument(node))) {
          +            throw new DOMException("WRONG_DOCUMENT_ERR");
          +        }
          +    }
          +
          +    // No current browsers conform fully to the HTML 5 draft spec for this method, so Rangy's own method is always used
          +    selProto.collapse = function(node, offset) {
          +        assertNodeInSameDocument(this, node);
          +        var range = api.createRange(dom.getDocument(node));
          +        range.collapseToPoint(node, offset);
          +        this.removeAllRanges();
          +        this.addRange(range);
          +        this.isCollapsed = true;
          +    };
          +
          +    selProto.collapseToStart = function() {
          +        if (this.rangeCount) {
          +            var range = this._ranges[0];
          +            this.collapse(range.startContainer, range.startOffset);
          +        } else {
          +            throw new DOMException("INVALID_STATE_ERR");
          +        }
          +    };
          +
          +    selProto.collapseToEnd = function() {
          +        if (this.rangeCount) {
          +            var range = this._ranges[this.rangeCount - 1];
          +            this.collapse(range.endContainer, range.endOffset);
          +        } else {
          +            throw new DOMException("INVALID_STATE_ERR");
          +        }
          +    };
          +
          +    // The HTML 5 spec is very specific on how selectAllChildren should be implemented so the native implementation is
          +    // never used by Rangy.
          +    selProto.selectAllChildren = function(node) {
          +        assertNodeInSameDocument(this, node);
          +        var range = api.createRange(dom.getDocument(node));
          +        range.selectNodeContents(node);
          +        this.removeAllRanges();
          +        this.addRange(range);
          +    };
          +
          +    selProto.deleteFromDocument = function() {
          +        // Sepcial behaviour required for Control selections
          +        if (implementsControlRange && implementsDocSelection && this.docSelection.type == CONTROL) {
          +            var controlRange = this.docSelection.createRange();
          +            var element;
          +            while (controlRange.length) {
          +                element = controlRange.item(0);
          +                controlRange.remove(element);
          +                element.parentNode.removeChild(element);
          +            }
          +            this.refresh();
          +        } else if (this.rangeCount) {
          +            var ranges = this.getAllRanges();
          +            this.removeAllRanges();
          +            for (var i = 0, len = ranges.length; i < len; ++i) {
          +                ranges[i].deleteContents();
          +            }
          +            // The HTML5 spec says nothing about what the selection should contain after calling deleteContents on each
          +            // range. Firefox moves the selection to where the final selected range was, so we emulate that
          +            this.addRange(ranges[len - 1]);
          +        }
          +    };
          +
          +    // The following are non-standard extensions
          +    selProto.getAllRanges = function() {
          +        return this._ranges.slice(0);
          +    };
          +
          +    selProto.setSingleRange = function(range) {
          +        this.setRanges( [range] );
          +    };
          +
          +    selProto.containsNode = function(node, allowPartial) {
          +        for (var i = 0, len = this._ranges.length; i < len; ++i) {
          +            if (this._ranges[i].containsNode(node, allowPartial)) {
          +                return true;
          +            }
          +        }
          +        return false;
          +    };
          +
          +    selProto.toHtml = function() {
          +        var html = "";
          +        if (this.rangeCount) {
          +            var container = DomRange.getRangeDocument(this._ranges[0]).createElement("div");
          +            for (var i = 0, len = this._ranges.length; i < len; ++i) {
          +                container.appendChild(this._ranges[i].cloneContents());
          +            }
          +            html = container.innerHTML;
          +        }
          +        return html;
          +    };
          +
          +    function inspect(sel) {
          +        var rangeInspects = [];
          +        var anchor = new DomPosition(sel.anchorNode, sel.anchorOffset);
          +        var focus = new DomPosition(sel.focusNode, sel.focusOffset);
          +        var name = (typeof sel.getName == "function") ? sel.getName() : "Selection";
          +
          +        if (typeof sel.rangeCount != "undefined") {
          +            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
          +                rangeInspects[i] = DomRange.inspect(sel.getRangeAt(i));
          +            }
          +        }
          +        return "[" + name + "(Ranges: " + rangeInspects.join(", ") +
          +                ")(anchor: " + anchor.inspect() + ", focus: " + focus.inspect() + "]";
          +
          +    }
          +
          +    selProto.getName = function() {
          +        return "WrappedSelection";
          +    };
          +
          +    selProto.inspect = function() {
          +        return inspect(this);
          +    };
          +
          +    selProto.detach = function() {
          +        this.win[windowPropertyName] = null;
          +        this.win = this.anchorNode = this.focusNode = null;
          +    };
          +
          +    WrappedSelection.inspect = inspect;
          +
          +    api.Selection = WrappedSelection;
          +
          +    api.selectionPrototype = selProto;
          +
          +    api.addCreateMissingNativeApiListener(function(win) {
          +        if (typeof win.getSelection == "undefined") {
          +            win.getSelection = function() {
          +                return api.getSelection(this);
          +            };
          +        }
          +        win = null;
          +    });
          +});
          +/*
          +	Base.js, version 1.1a
          +	Copyright 2006-2010, Dean Edwards
          +	License: http://www.opensource.org/licenses/mit-license.php
          +*/
          +
          +var Base = function() {
          +	// dummy
          +};
          +
          +Base.extend = function(_instance, _static) { // subclass
          +	var extend = Base.prototype.extend;
          +	
          +	// build the prototype
          +	Base._prototyping = true;
          +	var proto = new this;
          +	extend.call(proto, _instance);
          +  proto.base = function() {
          +    // call this method from any other method to invoke that method's ancestor
          +  };
          +	delete Base._prototyping;
          +	
          +	// create the wrapper for the constructor function
          +	//var constructor = proto.constructor.valueOf(); //-dean
          +	var constructor = proto.constructor;
          +	var klass = proto.constructor = function() {
          +		if (!Base._prototyping) {
          +			if (this._constructing || this.constructor == klass) { // instantiation
          +				this._constructing = true;
          +				constructor.apply(this, arguments);
          +				delete this._constructing;
          +			} else if (arguments[0] != null) { // casting
          +				return (arguments[0].extend || extend).call(arguments[0], proto);
          +			}
          +		}
          +	};
          +	
          +	// build the class interface
          +	klass.ancestor = this;
          +	klass.extend = this.extend;
          +	klass.forEach = this.forEach;
          +	klass.implement = this.implement;
          +	klass.prototype = proto;
          +	klass.toString = this.toString;
          +	klass.valueOf = function(type) {
          +		//return (type == "object") ? klass : constructor; //-dean
          +		return (type == "object") ? klass : constructor.valueOf();
          +	};
          +	extend.call(klass, _static);
          +	// class initialisation
          +	if (typeof klass.init == "function") klass.init();
          +	return klass;
          +};
          +
          +Base.prototype = {	
          +	extend: function(source, value) {
          +		if (arguments.length > 1) { // extending with a name/value pair
          +			var ancestor = this[source];
          +			if (ancestor && (typeof value == "function") && // overriding a method?
          +				// the valueOf() comparison is to avoid circular references
          +				(!ancestor.valueOf || ancestor.valueOf() != value.valueOf()) &&
          +				/\bbase\b/.test(value)) {
          +				// get the underlying method
          +				var method = value.valueOf();
          +				// override
          +				value = function() {
          +					var previous = this.base || Base.prototype.base;
          +					this.base = ancestor;
          +					var returnValue = method.apply(this, arguments);
          +					this.base = previous;
          +					return returnValue;
          +				};
          +				// point to the underlying method
          +				value.valueOf = function(type) {
          +					return (type == "object") ? value : method;
          +				};
          +				value.toString = Base.toString;
          +			}
          +			this[source] = value;
          +		} else if (source) { // extending with an object literal
          +			var extend = Base.prototype.extend;
          +			// if this object has a customised extend method then use it
          +			if (!Base._prototyping && typeof this != "function") {
          +				extend = this.extend || extend;
          +			}
          +			var proto = {toSource: null};
          +			// do the "toString" and other methods manually
          +			var hidden = ["constructor", "toString", "valueOf"];
          +			// if we are prototyping then include the constructor
          +			var i = Base._prototyping ? 0 : 1;
          +			while (key = hidden[i++]) {
          +				if (source[key] != proto[key]) {
          +					extend.call(this, key, source[key]);
          +
          +				}
          +			}
          +			// copy each of the source object's properties to this object
          +			for (var key in source) {
          +				if (!proto[key]) extend.call(this, key, source[key]);
          +			}
          +		}
          +		return this;
          +	}
          +};
          +
          +// initialise
          +Base = Base.extend({
          +	constructor: function() {
          +		this.extend(arguments[0]);
          +	}
          +}, {
          +	ancestor: Object,
          +	version: "1.1",
          +	
          +	forEach: function(object, block, context) {
          +		for (var key in object) {
          +			if (this.prototype[key] === undefined) {
          +				block.call(context, object[key], key, object);
          +			}
          +		}
          +	},
          +		
          +	implement: function() {
          +		for (var i = 0; i < arguments.length; i++) {
          +			if (typeof arguments[i] == "function") {
          +				// if it's a function, call it
          +				arguments[i](this.prototype);
          +			} else {
          +				// add the interface using the extend method
          +				this.prototype.extend(arguments[i]);
          +			}
          +		}
          +		return this;
          +	},
          +	
          +	toString: function() {
          +		return String(this.valueOf());
          +	}
          +});/**
          + * Detect browser support for specific features
          + */
          +wysihtml5.browser = (function() {
          +  var userAgent   = navigator.userAgent,
          +      testElement = document.createElement("div"),
          +      // Browser sniffing is unfortunately needed since some behaviors are impossible to feature detect
          +      isIE        = userAgent.indexOf("MSIE")         !== -1 && userAgent.indexOf("Opera") === -1,
          +      isGecko     = userAgent.indexOf("Gecko")        !== -1 && userAgent.indexOf("KHTML") === -1,
          +      isWebKit    = userAgent.indexOf("AppleWebKit/") !== -1,
          +      isChrome    = userAgent.indexOf("Chrome/")      !== -1,
          +      isOpera     = userAgent.indexOf("Opera/")       !== -1;
          +  
          +  function iosVersion(userAgent) {
          +    return ((/ipad|iphone|ipod/.test(userAgent) && userAgent.match(/ os (\d+).+? like mac os x/)) || [, 0])[1];
          +  }
          +  
          +  return {
          +    // Static variable needed, publicly accessible, to be able override it in unit tests
          +    USER_AGENT: userAgent,
          +    
          +    /**
          +     * Exclude browsers that are not capable of displaying and handling
          +     * contentEditable as desired:
          +     *    - iPhone, iPad (tested iOS 4.2.2) and Android (tested 2.2) refuse to make contentEditables focusable
          +     *    - IE < 8 create invalid markup and crash randomly from time to time
          +     *
          +     * @return {Boolean}
          +     */
          +    supported: function() {
          +      var userAgent                   = this.USER_AGENT.toLowerCase(),
          +          // Essential for making html elements editable
          +          hasContentEditableSupport   = "contentEditable" in testElement,
          +          // Following methods are needed in order to interact with the contentEditable area
          +          hasEditingApiSupport        = document.execCommand && document.queryCommandSupported && document.queryCommandState,
          +          // document selector apis are only supported by IE 8+, Safari 4+, Chrome and Firefox 3.5+
          +          hasQuerySelectorSupport     = document.querySelector && document.querySelectorAll,
          +          // contentEditable is unusable in mobile browsers (tested iOS 4.2.2, Android 2.2, Opera Mobile, WebOS 3.05)
          +          isIncompatibleMobileBrowser = (this.isIos() && iosVersion(userAgent) < 5) || userAgent.indexOf("opera mobi") !== -1 || userAgent.indexOf("hpwos/") !== -1;
          +      
          +      return hasContentEditableSupport
          +        && hasEditingApiSupport
          +        && hasQuerySelectorSupport
          +        && !isIncompatibleMobileBrowser;
          +    },
          +    
          +    isTouchDevice: function() {
          +      return this.supportsEvent("touchmove");
          +    },
          +    
          +    isIos: function() {
          +      var userAgent = this.USER_AGENT.toLowerCase();
          +      return userAgent.indexOf("webkit") !== -1 && userAgent.indexOf("mobile") !== -1;
          +    },
          +    
          +    /**
          +     * Whether the browser supports sandboxed iframes
          +     * Currently only IE 6+ offers such feature ').load(function () {
          +                            initFrame.call(me);
          +                        });
          +                    }
          +                    else {
          +                        this.$content = this.$editor = $('
          '); + } + + var classlist = this.$el.get(0).className.split(/\s+/); + $.each(classlist, $.proxy(function (i, s) { + this.$content.addClass('redactor_' + s); + }, this)); + } + else { + this.textareamode = false; + this.$content = this.$editor = this.$el; + this.$el = $('').css('height', this.height); + } + + if (this.$editor) { + this.$editor.addClass('redactor_editor').attr('contenteditable', true).attr('dir', this.opts.direction); + } + + if (this.opts.tabindex !== false) { + this.$content.attr('tabindex', this.opts.tabindex); + } + + if (this.opts.minHeight !== false) { + this.$content.css('min-height', this.opts.minHeight + 'px'); + } + + if (this.opts.wym === true) { + this.$content.addClass('redactor_editor_wym'); + } + + if (this.opts.autoresize === false) { + this.$content.css('height', this.height); + } + + // hide textarea + this.$el.hide(); + + // append box and frame + var html = ''; + if (this.textareamode) { + // get html + html = this.$el.val(); + html = this.savePreCode(html); + + this.$box.insertAfter(this.$el).append(this.$content).append(this.$el); + } + else { + // get html + html = this.$editor.html(); + html = this.savePreCode(html); + + this.$box.insertAfter(this.$content).append(this.$el).append(this.$editor); + + } + + // conver newlines to p + html = this.paragraphy(html); + + // enable + if (this.$editor) { + this.$editor.html(html); + } + + if (this.textareamode === false) { + this.syncCode(); + } + } + else { + if (this.$el.get(0).tagName !== 'TEXTAREA') { + var html = this.$el.val(); + var textarea = $('').css('height', this.height).val(html); + this.$el.hide(); + this.$el.after(textarea); + } + } + + if (whendone && this.$editor) { + whendone.call(this); + } + + }, + enableAir: function () { + if (this.opts.air === false) { + return false; + } + + this.air.hide(); + + this.$editor.bind('textselect', $.proxy(function (e) { + this.showAir(e); + + }, this)); + + this.$editor.bind('textunselect', $.proxy(function () { + this.air.hide(); + + }, this)); + + }, + showAir: function (e) { + $('.redactor_air').hide(); + + var width = this.air.innerWidth(); + var left = e.clientX; + + if ($(this.document).width() < (left + width)) { + left = left - width; + } + + var top = e.clientY + $(document).scrollTop() + 14; + if (this.opts.iframe === true) { + top = top + this.$box.position().top; + left = left + this.$box.position().left; + } + + this.air.css({ left: left + 'px', top: top + 'px' }).show(); + }, + syncCode: function () { + this.$el.val(this.$editor.html()); + }, + + // API functions + setCode: function (html) { + html = this.stripTags(html); + this.$editor.html(html).focus(); + + this.syncCode(); + }, + getCode: function () { + var html = ''; + if (this.opts.visual) { + html = this.$editor.html() + } + else { + html = this.$el.val(); + } + + return this.stripTags(html); + }, + insertHtml: function (html) { + this.$editor.focus(); + this.pasteHtmlAtCaret(html); + this.observeImages(); + this.syncCode(); + }, + + pasteHtmlAtCaret: function (html) { + var sel, range; + if (this.document.getSelection) { + sel = this.window.getSelection(); + if (sel.getRangeAt && sel.rangeCount) { + range = sel.getRangeAt(0); + range.deleteContents(); + var el = this.document.createElement("div"); + el.innerHTML = html; + var frag = this.document.createDocumentFragment(), node, lastNode; + while (node = el.firstChild) { + lastNode = frag.appendChild(node); + } + range.insertNode(frag); + + if (lastNode) { + range = range.cloneRange(); + range.setStartAfter(lastNode); + range.collapse(true); + sel.removeAllRanges(); + sel.addRange(range); + } + } + } + else if (this.document.selection && this.document.selection.type != "Control") { + this.document.selection.createRange().pasteHTML(html); + } + }, + + destroy: function () { + var html = this.getCode(); + + if (this.textareamode) { + this.$box.after(this.$el); + this.$box.remove(); + this.$el.height(this.height).val(html).show(); + } + else { + this.$box.after(this.$editor); + this.$box.remove(); + this.$editor.removeClass('redactor_editor').removeClass('redactor_editor_wym').attr('contenteditable', false).html(html).show(); + } + + if (this.opts.toolbarExternal) { + $(this.opts.toolbarExternal).empty(); + } + + $('.redactor_air').remove(); + + for (var i = 0; i < this.dropdowns.length; i++) { + this.dropdowns[i].remove(); + delete(this.dropdowns[i]); + } + + if (this.opts.autosave !== false) { + clearInterval(this.autosaveInterval); + } + + }, + // end API functions + + // OBSERVERS + observeFormatting: function () { + var parent = this.getCurrentNode(); + + this.inactiveAllButtons(); + + $.each(this.opts.activeButtonsStates, $.proxy(function (i, s) { + if ($(parent).closest(i, this.$editor.get()[0]).length != 0) { + this.setBtnActive(s); + } + + }, this)); + + var tag = $(parent).closest(['p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'td']); + + if (typeof tag[0] !== 'undefined' && typeof tag[0].elem !== 'undefined' && $(tag[0].elem).size() != 0) { + var align = $(tag[0].elem).css('text-align'); + + switch (align) { + case 'right': + this.setBtnActive('alignright'); + break; + case 'center': + this.setBtnActive('aligncenter'); + break; + case 'justify': + this.setBtnActive('justify'); + break; + default: + this.setBtnActive('alignleft'); + break; + } + } + }, + observeImages: function () { + if (this.opts.observeImages === false) { + return false; + } + + this.$editor.find('img').each($.proxy(function (i, s) { + if (this.browser('msie')) { + $(s).attr('unselectable', 'on'); + } + + this.resizeImage(s); + + }, this)); + + }, + observeTables: function () { + this.$editor.find('table').click($.proxy(this.tableObserver, this)); + }, + observeScroll: function () { + var scrolltop = $(this.document).scrollTop(); + var boxtop = this.$box.offset().top; + var left = 0; + + if (scrolltop > boxtop) { + var width = '100%'; + if (this.opts.fixedBox) { + left = this.$box.offset().left; + width = this.$box.innerWidth(); + } + + this.fixed = true; + this.$toolbar.css({ position: 'fixed', width: width, zIndex: 1005, top: this.opts.fixedTop + 'px', left: left }); + } + else { + this.fixed = false; + this.$toolbar.css({ position: 'relative', width: 'auto', zIndex: 1, top: 0, left: left }); + } + }, + + // BUFFER + setBuffer: function () { + this.saveSelection(); + this.opts.buffer = this.$editor.html(); + }, + getBuffer: function () { + if (this.opts.buffer === false) { + return false; + } + + this.$editor.html(this.opts.buffer); + + if (!this.browser('msie')) { + this.restoreSelection(); + } + + this.opts.buffer = false; + }, + + + // EXECCOMMAND + execCommand: function (cmd, param) { + if (this.opts.visual == false) { + this.$el.focus(); + return false; + } + + try { + + var parent; + + if (cmd === 'inserthtml') { + if (this.browser('msie')) { + this.$editor.focus(); + this.document.selection.createRange().pasteHTML(param); + } + else { + this.pasteHtmlAtCaret(param); + //this.execRun(cmd, param); + } + + this.observeImages(); + } + else if (cmd === 'unlink') { + parent = this.getParentNode(); + if ($(parent).get(0).tagName === 'A') { + $(parent).replaceWith($(parent).text()); + } + else { + this.execRun(cmd, param); + } + } + else if (cmd === 'JustifyLeft' || cmd === 'JustifyCenter' || cmd === 'JustifyRight' || cmd === 'JustifyFull') { + parent = this.getCurrentNode(); + var tag = $(parent).get(0).tagName; + + if (this.opts.iframe === false && $(parent).parents('.redactor_editor').size() == 0) { + return false; + } + + var tagsArray = ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'TD']; + if ($.inArray(tag, tagsArray) != -1) { + var align = false; + + if (cmd === 'JustifyCenter') { + align = 'center'; + } + else if (cmd === 'JustifyRight') { + align = 'right'; + } + else if (cmd === 'JustifyFull') { + align = 'justify'; + } + + if (align === false) { + $(parent).css('text-align', ''); + } + else { + $(parent).css('text-align', align); + } + } + else { + this.execRun(cmd, param); + } + } + else if (cmd === 'formatblock' && param === 'blockquote') { + parent = this.getCurrentNode(); + if ($(parent).get(0).tagName === 'BLOCKQUOTE') { + if (this.browser('msie')) { + var node = $('

          ' + $(parent).html() + '

          '); + $(parent).replaceWith(node); + } + else { + this.execRun(cmd, 'p'); + } + } + else if ($(parent).get(0).tagName === 'P') { + var parent2 = $(parent).parent(); + if ($(parent2).get(0).tagName === 'BLOCKQUOTE') { + var node = $('

          ' + $(parent).html() + '

          '); + $(parent2).replaceWith(node); + this.setSelection(node[0], 0, node[0], 0); + } + else { + if (this.browser('msie')) { + var node = $('
          ' + $(parent).html() + '
          '); + $(parent).replaceWith(node); + } + else { + this.execRun(cmd, param); + } + } + } + else { + this.execRun(cmd, param); + } + } + else if (cmd === 'formatblock' && (param === 'pre' || param === 'p')) { + parent = this.getParentNode(); + + if ($(parent).get(0).tagName === 'PRE') { + $(parent).replaceWith('

          ' + this.encodeEntities($(parent).text()) + '

          '); + } + else { + this.execRun(cmd, param); + } + } + else { + if (cmd === 'inserthorizontalrule' && this.browser('msie')) { + this.$editor.focus(); + } + + if (cmd === 'formatblock' && this.browser('mozilla')) { + this.$editor.focus(); + } + + this.execRun(cmd, param); + } + + if (cmd === 'inserthorizontalrule') { + this.$editor.find('hr').removeAttr('id'); + } + + this.syncCode(); + + if (this.oldIE()) { + this.$editor.focus(); + } + + if (typeof this.opts.execCommandCallback === 'function') { + this.opts.execCommandCallback(this, cmd); + } + + if (this.opts.air) { + this.air.hide(); + } + } + catch (e) { + } + }, + execRun: function (cmd, param) { + if (cmd === 'formatblock' && this.browser('msie')) { + param = '<' + param + '>'; + } + + this.document.execCommand(cmd, false, param); + }, + + // FORMAT NEW LINE + formatNewLine: function (e) { + var parent = this.getParentNode(); + + if (parent.nodeName === 'DIV' && parent.className === 'redactor_editor') { + var element = $(this.getCurrentNode()); + + if (element.get(0).tagName === 'DIV' && (element.html() === '' || element.html() === '
          ')) { + var newElement = $('

          ').append(element.clone().get(0).childNodes); + element.replaceWith(newElement); + newElement.html('
          '); + this.setSelection(newElement[0], 0, newElement[0], 0); + } + } + }, + + // SAFARI SHIFT KEY + ENTER + safariShiftKeyEnter: function (e, key) { + if (e.shiftKey && key === 13) { + e.preventDefault(); + this.insertNodeAtCaret($('
          ').get(0)); + this.syncCode(); + return false; + } + else { + return true; + } + }, + + // FORMAT EMPTY + formatEmpty: function (e) { + var html = $.trim(this.$editor.html()); + + if (this.browser('mozilla')) { + html = html.replace(/
          /i, ''); + } + + var thtml = html.replace(/<(?:.|\n)*?>/gm, ''); + + if (html === '' || thtml === '') { + e.preventDefault(); + + var node = $(this.opts.emptyHtml).get(0); + this.$editor.html(node); + this.setSelection(node, 0, node, 0); + + this.syncCode(); + return false; + } + else { + this.syncCode(); + } + }, + + // PARAGRAPHY + paragraphy: function (str) { + str = $.trim(str); + if (str === '' || str === '

          ') { + return this.opts.emptyHtml; + } + + // convert div to p + if (this.opts.convertDivs) { + str = str.replace(/([\w\W]*?)<\/div>/gi, '

          $2

          '); + } + + // inner functions + var X = function (x, a, b) { + return x.replace(new RegExp(a, 'g'), b); + }; + var R = function (a, b) { + return X(str, a, b); + }; + + // block elements + var blocks = '(table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|style|script|object|input|param|p|h[1-6])'; + + //str = '

          ' + str; + str += '\n'; + + R('
          \\s*
          ', '\n\n'); + R('(<' + blocks + '[^>]*>)', '\n$1'); + R('()', '$1\n\n'); + R('\r\n|\r', '\n'); // newlines + R('\n\n+', '\n\n'); // remove duplicates + R('\n?((.|\n)+?)$', '

          $1

          \n'); // including one at the end + R('

          \\s*?

          ', ''); // remove empty p + R('

          (]*>\\s*)', '$1

          '); + R('

          ([^<]+)\\s*?(]*>)', '

          $1

          $2'); + R('

          \\s*(]*>)\\s*

          ', '$1'); + R('

          (', '$1'); + R('

          \\s*(]*>)', '$1'); + R('(]*>)\\s*

          ', '$1'); + R('(]*>)\\s*
          ', '$1'); + R('
          (\\s*]*>)', '$1'); + + // pre + if (str.indexOf(')((.|\n)*?)
          ', function (m0, m1, m2, m3) { + return X(m1, '\\\\([\'\"\\\\])', '$1') + X(X(X(m3, '

          ', '\n'), '

          |
          ', ''), '\\\\([\'\"\\\\])', '$1') + ''; + }); + } + + return R('\n

          $', '

          '); + }, + + // REMOVE TAGS + stripTags: function (html) { + var allowed = this.opts.allowedTags; + var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi; + return html.replace(tags, function ($0, $1) { + return $.inArray($1.toLowerCase(), allowed) > '-1' ? $0 : ''; + }); + }, + + + savePreCode: function (html) { + var pre = html.match(/([\w\W]*?)<\/pre>/gi); + if (pre !== null) { + $.each(pre, $.proxy(function (i, s) { + var arr = s.match(/([\w\W]*?)<\/pre>/i); + arr[2] = this.encodeEntities(arr[2]); + html = html.replace(s, '' + arr[2] + ''); + }, this)); + } + + return html; + }, + encodeEntities: function (str) { + str = String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); + return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); + }, + cleanupPre: function (s) { + s = s.replace(/
          /gi, '\n'); + s = s.replace(/<\/p>/gi, '\n'); + s = s.replace(/<\/div>/gi, '\n'); + + var tmp = this.document.createElement("div"); + tmp.innerHTML = s; + return tmp.textContent || tmp.innerText; + + }, + + + // PASTE CLEANUP + pasteCleanUp: function (html) { + var parent = this.getParentNode(); + + // clean up pre + if ($(parent).get(0).tagName === 'PRE') { + html = this.cleanupPre(html); + this.pasteCleanUpInsert(html); + return true; + } + + // remove comments and php tags + html = html.replace(/|<\?(?:php)?[\s\S]*?\?>/gi, ''); + + // remove nbsp + html = html.replace(/( ){2,}/gi, ' '); + + // remove google docs marker + html = html.replace(/([\w\W]*?)<\/b>/gi, "$2"); + + // strip tags + html = this.stripTags(html); + + // prevert + html = html.replace(/<\/td>/gi, '[td]'); + html = html.replace(/ <\/td>/gi, '[td]'); + html = html.replace(/
          <\/td>/gi, '[td]'); + html = html.replace(/([\w\W]*?)<\/a>/gi, '[a href="$2"]$4[/a]'); + html = html.replace(/([\w\W]*?)<\/iframe>/gi, '[iframe$1]$2[/iframe]'); + html = html.replace(/([\w\W]*?)<\/video>/gi, '[video$1]$2[/video]'); + html = html.replace(/([\w\W]*?)<\/audio>/gi, '[audio$1]$2[/audio]'); + html = html.replace(/([\w\W]*?)<\/embed>/gi, '[embed$1]$2[/embed]'); + html = html.replace(/([\w\W]*?)<\/object>/gi, '[object$1]$2[/object]'); + html = html.replace(//gi, '[param$1]'); + html = html.replace(//gi, '[img$1$3]'); + + // remove attributes + html = html.replace(/<(\w+)([\w\W]*?)>/gi, '<$1>'); + + // remove empty + html = html.replace(/<[^\/>][^>]*>(\s*|\t*|\n*| |
          )<\/[^>]+>/gi, ''); + html = html.replace(/<[^\/>][^>]*>(\s*|\t*|\n*| |
          )<\/[^>]+>/gi, ''); + + // revert + html = html.replace(/\[td\]/gi, ' '); + html = html.replace(/\[a href="(.*?)"\]([\w\W]*?)\[\/a\]/gi, '$2'); + html = html.replace(/\[iframe(.*?)\]([\w\W]*?)\[\/iframe\]/gi, '$2'); + html = html.replace(/\[video(.*?)\]([\w\W]*?)\[\/video\]/gi, '$2'); + html = html.replace(/\[audio(.*?)\]([\w\W]*?)\[\/audio\]/gi, '$2'); + html = html.replace(/\[embed(.*?)\]([\w\W]*?)\[\/embed\]/gi, '$2'); + html = html.replace(/\[object(.*?)\]([\w\W]*?)\[\/object\]/gi, '$2'); + html = html.replace(/\[param(.*?)\]/gi, ''); + html = html.replace(/\[img(.*?)\]/gi, ''); + + + // convert div to p + if (this.opts.convertDivs) { + html = html.replace(/([\w\W]*?)<\/div>/gi, '

          $2

          '); + } + + // remove span + html = html.replace(/([\w\W]*?)<\/span>/gi, '$1'); + + html = html.replace(/\n{3,}/gi, '\n'); + + // remove dirty p + html = html.replace(/

          /gi, '

          '); + html = html.replace(/<\/p><\/p>/gi, '

          '); + + // FF fix + if (this.browser('mozilla')) { + html = html.replace(/
          $/gi, ''); + } + + this.pasteCleanUpInsert(html); + + }, + + pasteCleanUpInsert: function (html) { + this.execCommand('inserthtml', html); + + if (this.opts.autoresize === true) { + $(this.document.body).scrollTop(this.saveScroll); + } + else { + this.$editor.scrollTop(this.saveScroll); + } + }, + + + // TEXTAREA CODE FORMATTING + formattingRemove: function (html) { + // save pre + var prebuffer = []; + var pre = html.match(/([\w\W]*?)<\/pre>/gi); + if (pre !== null) { + $.each(pre, function (i, s) { + html = html.replace(s, 'prebuffer_' + i); + prebuffer.push(s); + }); + } + + html = html.replace(/\s{2,}/g, ' '); + html = html.replace(/\n/g, ' '); + html = html.replace(/[\t]*/g, ''); + html = html.replace(/\n\s*\n/g, "\n"); + html = html.replace(/^[\s\n]*/g, ''); + html = html.replace(/[\s\n]*$/g, ''); + html = html.replace(/>\s+<'); + + if (prebuffer) { + $.each(prebuffer, function (i, s) { + html = html.replace('prebuffer_' + i, s); + }); + + prebuffer = []; + } + + return html; + }, + formattingIndenting: function (html) { + html = html.replace(/
        • /g, "\t"); + + return html; + }, + formattingEmptyTags: function (html) { + var etags = ["
          ", "
          \\s*
          ", "\\s*", "
            ", "
              ", "
            1. ", "
              ", "", "\\s*", " ", "\\s*", " ", "

              \\s*

              ", "

               

              ", "

              \\s*
              \\s*

              ", "
              \\s*
              ", "
              \\s*
              \\s*
              "]; + for (var i = 0; i < etags.length; ++i) { + var bbb = etags[i]; + html = html.replace(new RegExp(bbb, 'gi'), ""); + } + + return html; + }, + formattingAddBefore: function (html) { + var lb = '\r\n'; + var btags = ["", '', "", "', '
            ', '', '', '', '', '', '', '
            ', '
            ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']; + for (var i = 0; i < atags.length; ++i) { + var aaa = atags[i]; + html = html.replace(new RegExp(aaa, 'gi'), aaa + lb); + } + + return html; + }, + formatting: function (html) { + html = this.formattingRemove(html); + + // empty tags + html = this.formattingEmptyTags(html); + + // add formatting before + html = this.formattingAddBefore(html); + + // add formatting after + html = this.formattingAddAfter(html); + + // indenting + html = this.formattingIndenting(html); + + return html; + }, + + // TOGGLE + toggle: function () { + var html; + + if (this.opts.visual) { + var height = this.$editor.innerHeight(); + + this.$editor.hide(); + this.$content.hide(); + + html = this.$editor.html(); + //html = $.trim(this.formatting(html)); + + this.$el.height(height).val(html).show().focus(); + + this.setBtnActive('html'); + this.opts.visual = false; + } + else { + this.$el.hide(); + var html = this.$el.val(); + + //html = this.savePreCode(html); + + // clean up + //html = this.stripTags(html); + + // set code + this.$editor.html(html).show(); + this.$content.show(); + + if (this.$editor.html() === '') { + this.setCode(this.opts.emptyHtml); + } + + this.$editor.focus(); + + this.setBtnInactive('html'); + this.opts.visual = true; + + this.observeImages(); + this.observeTables(); + } + }, + + // AUTOSAVE + autoSave: function () { + this.autosaveInterval = setInterval($.proxy(function () { + $.ajax({ + url: this.opts.autosave, + type: 'post', + data: this.$el.attr('name') + '=' + escape(encodeURIComponent(this.getCode())), + success: $.proxy(function (data) { + // callback + if (typeof this.opts.autosaveCallback === 'function') { + this.opts.autosaveCallback(data, this); + } + + }, this) + }); + + + }, this), this.opts.interval * 1000); + }, + + // TOOLBAR + buildToolbar: function () { + if (this.opts.toolbar === false) { + return false; + } + + this.$toolbar = $('
              ').addClass('redactor_toolbar'); + + if (this.opts.air) { + $(this.air).append(this.$toolbar); + $('body').append(this.air); + } + else { + if (this.opts.toolbarExternal === false) { + this.$box.prepend(this.$toolbar); + } + else { + $(this.opts.toolbarExternal).html(this.$toolbar); + } + } + + $.each(this.opts.buttons, $.proxy(function (i, key) { + + if (key !== '|' && typeof this.opts.toolbar[key] !== 'undefined') { + var s = this.opts.toolbar[key]; + + if (this.opts.fileUpload === false && key === 'file') { + return true; + } + + this.$toolbar.append($('
            • ').append(this.buildButton(key, s))); + } + + + if (key === '|') { + this.$toolbar.append($('
            • ')); + } + + }, this)); + + }, + buildButton: function (key, s) { + var button = $(''); + + if (typeof s.func === 'undefined') { + button.click($.proxy(function () { + if ($.inArray(key, this.opts.activeButtons) != -1) { + this.inactiveAllButtons(); + this.setBtnActive(key); + } + + if (this.browser('mozilla')) { + this.$editor.focus(); + //this.restoreSelection(); + } + + this.execCommand(s.exec, key); + + }, this)); + } + else if (s.func !== 'show') { + button.click($.proxy(function (e) { + + this[s.func](e); + + }, this)); + } + + if (typeof s.callback !== 'undefined' && s.callback !== false) { + button.click($.proxy(function (e) { + s.callback(this, e, key); + }, this)); + } + + // dropdown + if (key === 'backcolor' || key === 'fontcolor' || typeof(s.dropdown) !== 'undefined') { + var dropdown = $('
              \n"; + } + + /** + * Renders the summary text. + */ + public function renderSummary() + { + if(($count=$this->dataProvider->getItemCount())<=0) + return; + + echo '
              '; + if($this->enablePagination) + { + $pagination=$this->dataProvider->getPagination(); + $total=$this->dataProvider->getTotalItemCount(); + $start=$pagination->currentPage*$pagination->pageSize+1; + $end=$start+$count-1; + if($end>$total) + { + $end=$total; + $start=$end-$count+1; + } + if(($summaryText=$this->summaryText)===null) + $summaryText=Yii::t('zii','Displaying {start}-{end} of 1 result.|Displaying {start}-{end} of {count} results.',$total); + echo strtr($summaryText,array( + '{start}'=>$start, + '{end}'=>$end, + '{count}'=>$total, + '{page}'=>$pagination->currentPage+1, + '{pages}'=>$pagination->pageCount, + )); + } + else + { + if(($summaryText=$this->summaryText)===null) + $summaryText=Yii::t('zii','Total 1 result.|Total {count} results.',$count); + echo strtr($summaryText,array( + '{count}'=>$count, + '{start}'=>1, + '{end}'=>$count, + '{page}'=>1, + '{pages}'=>1, + )); + } + echo '
              '; + } + + /** + * Renders the pager. + */ + public function renderPager() + { + if(!$this->enablePagination) + return; + + $pager=array(); + $class='CLinkPager'; + if(is_string($this->pager)) + $class=$this->pager; + elseif(is_array($this->pager)) + { + $pager=$this->pager; + if(isset($pager['class'])) + { + $class=$pager['class']; + unset($pager['class']); + } + } + $pager['pages']=$this->dataProvider->getPagination(); + + if($pager['pages']->getPageCount()>1) + { + echo '
              '; + $this->widget($class,$pager); + echo '
              '; + } + else + $this->widget($class,$pager); + } + + /** + * Registers necessary client scripts. + * This method is invoked by {@link run}. + * Child classes may override this method to register customized client scripts. + */ + public function registerClientScript() + { + } + + /** + * Renders the data items for the view. + * Each item is corresponding to a single data model instance. + * Child classes should override this method to provide the actual item rendering logic. + */ + abstract public function renderItems(); +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CBreadcrumbs.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CBreadcrumbs.php new file mode 100644 index 0000000..440f240 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CBreadcrumbs.php @@ -0,0 +1,132 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CBreadcrumbs displays a list of links indicating the position of the current page in the whole website. + * + * For example, breadcrumbs like "Home > Sample Post > Edit" means the user is viewing an edit page + * for the "Sample Post". He can click on "Sample Post" to view that page, or he can click on "Home" + * to return to the homepage. + * + * To use CBreadcrumbs, one usually needs to configure its {@link links} property, which specifies + * the links to be displayed. For example, + * + *
              + * $this->widget('zii.widgets.CBreadcrumbs', array(
              + *     'links'=>array(
              + *         'Sample post'=>array('post/view', 'id'=>12),
              + *         'Edit',
              + *     ),
              + * ));
              + * 
              + * + * Because breadcrumbs usually appears in nearly every page of a website, the widget is better to be placed + * in a layout view. One can define a property "breadcrumbs" in the base controller class and assign it to the widget + * in the layout, like the following: + * + *
              + * $this->widget('zii.widgets.CBreadcrumbs', array(
              + *     'links'=>$this->breadcrumbs,
              + * ));
              + * 
              + * + * Then, in each view script, one only needs to assign the "breadcrumbs" property as needed. + * + * @author Qiang Xue + * @package zii.widgets + * @since 1.1 + */ +class CBreadcrumbs extends CWidget +{ + /** + * @var string the tag name for the breadcrumbs container tag. Defaults to 'div'. + */ + public $tagName='div'; + /** + * @var array the HTML attributes for the breadcrumbs container tag. + */ + public $htmlOptions=array('class'=>'breadcrumbs'); + /** + * @var boolean whether to HTML encode the link labels. Defaults to true. + */ + public $encodeLabel=true; + /** + * @var string the first hyperlink in the breadcrumbs (called home link). + * If this property is not set, it defaults to a link pointing to {@link CWebApplication::homeUrl} with label 'Home'. + * If this property is false, the home link will not be rendered. + */ + public $homeLink; + /** + * @var array list of hyperlinks to appear in the breadcrumbs. If this property is empty, + * the widget will not render anything. Each key-value pair in the array + * will be used to generate a hyperlink by calling CHtml::link(key, value). For this reason, the key + * refers to the label of the link while the value can be a string or an array (used to + * create a URL). For more details, please refer to {@link CHtml::link}. + * If an element's key is an integer, it means the element will be rendered as a label only (meaning the current page). + * + * The following example will generate breadcrumbs as "Home > Sample post > Edit", where "Home" points to the homepage, + * "Sample post" points to the "index.php?r=post/view&id=12" page, and "Edit" is a label. Note that the "Home" link + * is specified via {@link homeLink} separately. + * + *
              +	 * array(
              +	 *     'Sample post'=>array('post/view', 'id'=>12),
              +	 *     'Edit',
              +	 * )
              +	 * 
              + */ + public $links=array(); + /** + * @var string String, specifies how each active item is rendered. Defaults to + * "{label}", where "{label}" will be replaced by the corresponding item + * label while "{url}" will be replaced by the URL of the item. + * @since 1.1.11 + */ + public $activeLinkTemplate='{label}'; + /** + * @var string String, specifies how each inactive item is rendered. Defaults to + * "{label}", where "{label}" will be replaced by the corresponding item label. + * Note that inactive template does not have "{url}" parameter. + * @since 1.1.11 + */ + public $inactiveLinkTemplate='{label}'; + /** + * @var string the separator between links in the breadcrumbs. Defaults to ' » '. + */ + public $separator=' » '; + + /** + * Renders the content of the portlet. + */ + public function run() + { + if(empty($this->links)) + return; + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + $links=array(); + if($this->homeLink===null) + $links[]=CHtml::link(Yii::t('zii','Home'),Yii::app()->homeUrl); + elseif($this->homeLink!==false) + $links[]=$this->homeLink; + foreach($this->links as $label=>$url) + { + if(is_string($label) || is_array($url)) + $links[]=strtr($this->activeLinkTemplate,array( + '{url}'=>CHtml::normalizeUrl($url), + '{label}'=>$this->encodeLabel ? CHtml::encode($label) : $label, + )); + else + $links[]=str_replace('{label}',$this->encodeLabel ? CHtml::encode($url) : $url,$this->inactiveLinkTemplate); + } + echo implode($this->separator,$links); + echo CHtml::closeTag($this->tagName); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CDetailView.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CDetailView.php new file mode 100644 index 0000000..5e46589 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CDetailView.php @@ -0,0 +1,255 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CDetailView displays the detail of a single data model. + * + * CDetailView is best used for displaying a model in a regular format (e.g. each model attribute + * is displayed as a row in a table.) The model can be either an instance of {@link CModel} + * or an associative array. + * + * CDetailView uses the {@link attributes} property to determines which model attributes + * should be displayed and how they should be formatted. + * + * A typical usage of CDetailView is as follows: + *
              + * $this->widget('zii.widgets.CDetailView', array(
              + *     'data'=>$model,
              + *     'attributes'=>array(
              + *         'title',             // title attribute (in plain text)
              + *         'owner.name',        // an attribute of the related object "owner"
              + *         'description:html',  // description attribute in HTML
              + *         array(               // related city displayed as a link
              + *             'label'=>'City',
              + *             'type'=>'raw',
              + *             'value'=>CHtml::link(CHtml::encode($model->city->name),
              + *                                  array('city/view','id'=>$model->city->id)),
              + *         ),
              + *     ),
              + * ));
              + * 
              + * + * @property CFormatter $formatter The formatter instance. Defaults to the 'format' application component. + * + * @author Qiang Xue + * @package zii.widgets + * @since 1.1 + */ +class CDetailView extends CWidget +{ + private $_formatter; + + /** + * @var mixed the data model whose details are to be displayed. This can be either a {@link CModel} instance + * (e.g. a {@link CActiveRecord} object or a {@link CFormModel} object) or an associative array. + */ + public $data; + /** + * @var array a list of attributes to be displayed in the detail view. Each array element + * represents the specification for displaying one particular attribute. + * + * An attribute can be specified as a string in the format of "Name:Type:Label". + * Both "Type" and "Label" are optional. + * + * "Name" refers to the attribute name. It can be either a property (e.g. "title") or a sub-property (e.g. "owner.username"). + * + * "Label" represents the label for the attribute display. If it is not given, "Name" will be used to generate the appropriate label. + * + * "Type" represents the type of the attribute. It determines how the attribute value should be formatted and displayed. + * It is defaulted to be 'text'. + * "Type" should be recognizable by the {@link formatter}. In particular, if "Type" is "xyz", then the "formatXyz" method + * of {@link formatter} will be invoked to format the attribute value for display. By default when {@link CFormatter} is used, + * these "Type" values are valid: raw, text, ntext, html, date, time, datetime, boolean, number, email, image, url. + * For more details about these types, please refer to {@link CFormatter}. + * + * An attribute can also be specified in terms of an array with the following elements: + *
                + *
              • label: the label associated with the attribute. If this is not specified, the following "name" element + * will be used to generate an appropriate label.
              • + *
              • name: the name of the attribute. This can be either a property or a sub-property of the model. + * If the below "value" element is specified, this will be ignored.
              • + *
              • value: the value to be displayed. If this is not specified, the above "name" element will be used + * to retrieve the corresponding attribute value for display. Note that this value will be formatted according + * to the "type" option as described below.
              • + *
              • type: the type of the attribute that determines how the attribute value would be formatted. + * Please see above for possible values. + *
              • cssClass: the CSS class to be used for this item. This option is available since version 1.1.3.
              • + *
              • template: the template used to render the attribute. If this is not specified, {@link itemTemplate} + * will be used instead. For more details on how to set this option, please refer to {@link itemTemplate}. + * This option is available since version 1.1.1.
              • + *
              • visible: whether the attribute is visible. If set to false, the table row for the attribute will not be rendered. + * This option is available since version 1.1.5.
              • + *
              + */ + public $attributes; + /** + * @var string the text to be displayed when an attribute value is null. Defaults to "Not set". + */ + public $nullDisplay; + /** + * @var string the name of the tag for rendering the detail view. Defaults to 'table'. + * If set to null, no tag will be rendered. + * @see itemTemplate + */ + public $tagName='table'; + /** + * @var string the template used to render a single attribute. Defaults to a table row. + * These tokens are recognized: "{class}", "{label}" and "{value}". They will be replaced + * with the CSS class name for the item, the label and the attribute value, respectively. + * @see itemCssClass + */ + public $itemTemplate="{label}{value}\n"; + /** + * @var array the CSS class names for the items displaying attribute values. If multiple CSS class names are given, + * they will be assigned to the items sequentially and repeatedly. + * Defaults to array('odd', 'even'). + */ + public $itemCssClass=array('odd','even'); + /** + * @var array the HTML options used for {@link tagName} + */ + public $htmlOptions=array('class'=>'detail-view'); + /** + * @var string the base script URL for all detail view resources (e.g. javascript, CSS file, images). + * Defaults to null, meaning using the integrated detail view resources (which are published as assets). + */ + public $baseScriptUrl; + /** + * @var string the URL of the CSS file used by this detail view. Defaults to null, meaning using the integrated + * CSS file. If this is set false, you are responsible to explicitly include the necessary CSS file in your page. + */ + public $cssFile; + + /** + * Initializes the detail view. + * This method will initialize required property values. + */ + public function init() + { + if($this->data===null) + throw new CException(Yii::t('zii','Please specify the "data" property.')); + if($this->attributes===null) + { + if($this->data instanceof CModel) + $this->attributes=$this->data->attributeNames(); + elseif(is_array($this->data)) + $this->attributes=array_keys($this->data); + else + throw new CException(Yii::t('zii','Please specify the "attributes" property.')); + } + if($this->nullDisplay===null) + $this->nullDisplay=''.Yii::t('zii','Not set').''; + $this->htmlOptions['id']=$this->getId(); + + if($this->baseScriptUrl===null) + $this->baseScriptUrl=Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('zii.widgets.assets')).'/detailview'; + + if($this->cssFile!==false) + { + if($this->cssFile===null) + $this->cssFile=$this->baseScriptUrl.'/styles.css'; + Yii::app()->getClientScript()->registerCssFile($this->cssFile); + } + } + + /** + * Renders the detail view. + * This is the main entry of the whole detail view rendering. + */ + public function run() + { + $formatter=$this->getFormatter(); + if ($this->tagName!==null) + echo CHtml::openTag($this->tagName,$this->htmlOptions); + + $i=0; + $n=is_array($this->itemCssClass) ? count($this->itemCssClass) : 0; + + foreach($this->attributes as $attribute) + { + if(is_string($attribute)) + { + if(!preg_match('/^([\w\.]+)(:(\w*))?(:(.*))?$/',$attribute,$matches)) + throw new CException(Yii::t('zii','The attribute must be specified in the format of "Name:Type:Label", where "Type" and "Label" are optional.')); + $attribute=array( + 'name'=>$matches[1], + 'type'=>isset($matches[3]) ? $matches[3] : 'text', + ); + if(isset($matches[5])) + $attribute['label']=$matches[5]; + } + + if(isset($attribute['visible']) && !$attribute['visible']) + continue; + + $tr=array('{label}'=>'', '{class}'=>$n ? $this->itemCssClass[$i%$n] : ''); + if(isset($attribute['cssClass'])) + $tr['{class}']=$attribute['cssClass'].' '.($n ? $tr['{class}'] : ''); + + if(isset($attribute['label'])) + $tr['{label}']=$attribute['label']; + elseif(isset($attribute['name'])) + { + if($this->data instanceof CModel) + $tr['{label}']=$this->data->getAttributeLabel($attribute['name']); + else + $tr['{label}']=ucwords(trim(strtolower(str_replace(array('-','_','.'),' ',preg_replace('/(?data) : $attribute['value']; + elseif(isset($attribute['name'])) + $value=CHtml::value($this->data,$attribute['name']); + else + $value=null; + + $tr['{value}']=$value===null ? $this->nullDisplay : $formatter->format($value,$attribute['type']); + + $this->renderItem($attribute, $tr); + + $i++; + } + + if ($this->tagName!==null) + echo CHtml::closeTag($this->tagName); + } + + /** + * This method is used by run() to render item row + * + * @param array $options config options for this item/attribute from {@link attributes} + * @param string $templateData data that will be inserted into {@link itemTemplate} + * @since 1.1.11 + */ + protected function renderItem($options,$templateData) + { + echo strtr(isset($options['template']) ? $options['template'] : $this->itemTemplate,$templateData); + } + + /** + * @return CFormatter the formatter instance. Defaults to the 'format' application component. + */ + public function getFormatter() + { + if($this->_formatter===null) + $this->_formatter=Yii::app()->format; + return $this->_formatter; + } + + /** + * @param CFormatter $value the formatter instance + */ + public function setFormatter($value) + { + $this->_formatter=$value; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CListView.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CListView.php new file mode 100644 index 0000000..079019e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CListView.php @@ -0,0 +1,325 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.CBaseListView'); + +/** + * CListView displays a list of data items in terms of a list. + * + * Unlike {@link CGridView} which displays the data items in a table, CListView allows one to use + * a view template to render each data item. As a result, CListView could generate more flexible + * rendering result. + * + * CListView supports both sorting and pagination of the data items. The sorting + * and pagination can be done in AJAX mode or normal page request. A benefit of using CListView is that + * when the user browser disables JavaScript, the sorting and pagination automatically degenerate + * to normal page requests and are still functioning as expected. + * + * CListView should be used together with a {@link IDataProvider data provider}, preferrably a + * {@link CActiveDataProvider}. + * + * The minimal code needed to use CListView is as follows: + * + *
              + * $dataProvider=new CActiveDataProvider('Post');
              + *
              + * $this->widget('zii.widgets.CListView', array(
              + *     'dataProvider'=>$dataProvider,
              + *     'itemView'=>'_post',   // refers to the partial view named '_post'
              + *     'sortableAttributes'=>array(
              + *         'title',
              + *         'create_time'=>'Post Time',
              + *     ),
              + * ));
              + * 
              + * + * The above code first creates a data provider for the Post ActiveRecord class. + * It then uses CListView to display every data item as returned by the data provider. + * The display is done via the partial view named '_post'. This partial view will be rendered + * once for every data item. In the view, one can access the current data item via variable $data. + * For more details, see {@link itemView}. + * + * In order to support sorting, one has to specify the {@link sortableAttributes} property. + * By doing so, a list of hyperlinks that can sort the data will be displayed. + * + * @author Qiang Xue + * @package zii.widgets + * @since 1.1 + */ +class CListView extends CBaseListView +{ + /** + * @var string the view used for rendering each data item. + * This property value will be passed as the first parameter to either {@link CController::renderPartial} + * or {@link CWidget::render} to render each data item. + * In the corresponding view template, the following variables can be used in addition to those declared in {@link viewData}: + *
                + *
              • $this: refers to the owner of this list view widget. For example, if the widget is in the view of a controller, + * then $this refers to the controller.
              • + *
              • $data: refers to the data item currently being rendered.
              • + *
              • $index: refers to the zero-based index of the data item currently being rendered.
              • + *
              • $widget: refers to this list view widget instance.
              • + *
              + */ + public $itemView; + /** + * @var string the HTML code to be displayed between any two consecutive items. + * @since 1.1.7 + */ + public $separator; + /** + * @var array additional data to be passed to {@link itemView} when rendering each data item. + * This array will be extracted into local PHP variables that can be accessed in the {@link itemView}. + */ + public $viewData=array(); + /** + * @var array list of sortable attribute names. In order for an attribute to be sortable, it must also + * appear as a sortable attribute in the {@link IDataProvider::sort} property of {@link dataProvider}. + * @see enableSorting + */ + public $sortableAttributes; + /** + * @var string the template to be used to control the layout of various components in the list view. + * These tokens are recognized: {summary}, {sorter}, {items} and {pager}. They will be replaced with the + * summary text, the sort links, the data item list, and the pager. + */ + public $template="{summary}\n{sorter}\n{items}\n{pager}"; + /** + * @var string the CSS class name that will be assigned to the widget container element + * when the widget is updating its content via AJAX. Defaults to 'list-view-loading'. + * @since 1.1.1 + */ + public $loadingCssClass='list-view-loading'; + /** + * @var string the CSS class name for the sorter container. Defaults to 'sorter'. + */ + public $sorterCssClass='sorter'; + /** + * @var string the text shown before sort links. Defaults to 'Sort by: '. + */ + public $sorterHeader; + /** + * @var string the text shown after sort links. Defaults to empty. + */ + public $sorterFooter=''; + /** + * @var mixed the ID of the container whose content may be updated with an AJAX response. + * Defaults to null, meaning the container for this list view instance. + * If it is set false, it means sorting and pagination will be performed in normal page requests + * instead of AJAX requests. If the sorting and pagination should trigger the update of multiple + * containers' content in AJAX fashion, these container IDs may be listed here (separated with comma). + */ + public $ajaxUpdate; + /** + * @var string the jQuery selector of the HTML elements that may trigger AJAX updates when they are clicked. + * If not set, the pagination links and the sorting links will trigger AJAX updates. + * @since 1.1.7 + */ + public $updateSelector; + /** + * @var string a javascript function that will be invoked if an AJAX update error occurs. + * + * The function signature is function(xhr, textStatus, errorThrown, errorMessage) + *
                + *
              • xhr is the XMLHttpRequest object.
              • + *
              • textStatus is a string describing the type of error that occurred. + * Possible values (besides null) are "timeout", "error", "notmodified" and "parsererror"
              • + *
              • errorThrown is an optional exception object, if one occurred.
              • + *
              • errorMessage is the CGridView default error message derived from xhr and errorThrown. + * Usefull if you just want to display this error differently. CGridView by default displays this error with an javascript.alert()
              • + *
              + * Note: This handler is not called for JSONP requests, because they do not use an XMLHttpRequest. + * + * Example (add in a call to CGridView): + *
              +	 *  ...
              +	 *  'ajaxUpdateError'=>'function(xhr,ts,et,err){ $("#myerrordiv").text(err); }',
              +	 *  ...
              +	 * 
              + * @since 1.1.13 + */ + public $ajaxUpdateError; + /** + * @var string the name of the GET variable that indicates the request is an AJAX request triggered + * by this widget. Defaults to 'ajax'. This is effective only when {@link ajaxUpdate} is not false. + */ + public $ajaxVar='ajax'; + /** + * @var mixed the URL for the AJAX requests should be sent to. {@link CHtml::normalizeUrl()} will be + * called on this property. If not set, the current page URL will be used for AJAX requests. + * @since 1.1.8 + */ + public $ajaxUrl; + /** + * @var string the type ('GET' or 'POST') of the AJAX requests. If not set, 'GET' will be used. + * You can set this to 'POST' if you are filtering by many fields at once and have a problem with GET query string length. + * Note that in POST mode direct links and {@link enableHistory} feature may not work correctly! + * @since 1.1.14 + */ + public $ajaxType; + /** + * @var string a javascript function that will be invoked before an AJAX update occurs. + * The function signature is function(id) where 'id' refers to the ID of the list view. + */ + public $beforeAjaxUpdate; + /** + * @var string a javascript function that will be invoked after a successful AJAX response is received. + * The function signature is function(id, data) where 'id' refers to the ID of the list view + * 'data' the received ajax response data. + */ + public $afterAjaxUpdate; + /** + * @var string the base script URL for all list view resources (e.g. javascript, CSS file, images). + * Defaults to null, meaning using the integrated list view resources (which are published as assets). + */ + public $baseScriptUrl; + /** + * @var string the URL of the CSS file used by this list view. Defaults to null, meaning using the integrated + * CSS file. If this is set false, you are responsible to explicitly include the necessary CSS file in your page. + */ + public $cssFile; + /** + * @var string the HTML tag name for the container of all data item display. Defaults to 'div'. + * @since 1.1.4 + */ + public $itemsTagName='div'; + + /** + * @var boolean whether to leverage the {@link https://developer.mozilla.org/en/DOM/window.history DOM history object}. Set this property to true + * to persist state of list across page revisits. Note, there are two limitations for this feature: + * - this feature is only compatible with browsers that support HTML5. + * - expect unexpected functionality (e.g. multiple ajax calls) if there is more than one grid/list on a single page with enableHistory turned on. + * @since 1.1.11 + */ + public $enableHistory=false; + + /** + * Initializes the list view. + * This method will initialize required property values and instantiate {@link columns} objects. + */ + public function init() + { + if($this->itemView===null) + throw new CException(Yii::t('zii','The property "itemView" cannot be empty.')); + parent::init(); + + if(!isset($this->htmlOptions['class'])) + $this->htmlOptions['class']='list-view'; + + if($this->baseScriptUrl===null) + $this->baseScriptUrl=Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('zii.widgets.assets')).'/listview'; + + if($this->cssFile!==false) + { + if($this->cssFile===null) + $this->cssFile=$this->baseScriptUrl.'/styles.css'; + Yii::app()->getClientScript()->registerCssFile($this->cssFile); + } + } + + /** + * Registers necessary client scripts. + */ + public function registerClientScript() + { + $id=$this->getId(); + + if($this->ajaxUpdate===false) + $ajaxUpdate=array(); + else + $ajaxUpdate=array_unique(preg_split('/\s*,\s*/',$this->ajaxUpdate.','.$id,-1,PREG_SPLIT_NO_EMPTY)); + $options=array( + 'ajaxUpdate'=>$ajaxUpdate, + 'ajaxVar'=>$this->ajaxVar, + 'pagerClass'=>$this->pagerCssClass, + 'loadingClass'=>$this->loadingCssClass, + 'sorterClass'=>$this->sorterCssClass, + 'enableHistory'=>$this->enableHistory + ); + if($this->ajaxUrl!==null) + $options['url']=CHtml::normalizeUrl($this->ajaxUrl); + if($this->ajaxType!==null) + $options['ajaxType']=strtoupper($this->ajaxType); + if($this->updateSelector!==null) + $options['updateSelector']=$this->updateSelector; + foreach(array('beforeAjaxUpdate', 'afterAjaxUpdate', 'ajaxUpdateError') as $event) + { + if($this->$event!==null) + { + if($this->$event instanceof CJavaScriptExpression) + $options[$event]=$this->$event; + else + $options[$event]=new CJavaScriptExpression($this->$event); + } + } + + $options=CJavaScript::encode($options); + $cs=Yii::app()->getClientScript(); + $cs->registerCoreScript('jquery'); + $cs->registerCoreScript('bbq'); + if($this->enableHistory) + $cs->registerCoreScript('history'); + $cs->registerScriptFile($this->baseScriptUrl.'/jquery.yiilistview.js',CClientScript::POS_END); + $cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiListView($options);"); + } + + /** + * Renders the data item list. + */ + public function renderItems() + { + echo CHtml::openTag($this->itemsTagName,array('class'=>$this->itemsCssClass))."\n"; + $data=$this->dataProvider->getData(); + if(($n=count($data))>0) + { + $owner=$this->getOwner(); + $viewFile=$owner->getViewFile($this->itemView); + $j=0; + foreach($data as $i=>$item) + { + $data=$this->viewData; + $data['index']=$i; + $data['data']=$item; + $data['widget']=$this; + $owner->renderFile($viewFile,$data); + if($j++ < $n-1) + echo $this->separator; + } + } + else + $this->renderEmptyText(); + echo CHtml::closeTag($this->itemsTagName); + } + + /** + * Renders the sorter. + */ + public function renderSorter() + { + if($this->dataProvider->getItemCount()<=0 || !$this->enableSorting || empty($this->sortableAttributes)) + return; + echo CHtml::openTag('div',array('class'=>$this->sorterCssClass))."\n"; + echo $this->sorterHeader===null ? Yii::t('zii','Sort by: ') : $this->sorterHeader; + echo "
                \n"; + $sort=$this->dataProvider->getSort(); + foreach($this->sortableAttributes as $name=>$label) + { + echo "
              • "; + if(is_integer($name)) + echo $sort->link($label); + else + echo $sort->link($name,$label); + echo "
              • \n"; + } + echo "
              "; + echo $this->sorterFooter; + echo CHtml::closeTag('div'); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CMenu.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CMenu.php new file mode 100644 index 0000000..42bb32e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CMenu.php @@ -0,0 +1,323 @@ + + * @author Qiang Xue + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CMenu displays a multi-level menu using nested HTML lists. + * + * The main property of CMenu is {@link items}, which specifies the possible items in the menu. + * A menu item has three main properties: visible, active and items. The "visible" property + * specifies whether the menu item is currently visible. The "active" property specifies whether + * the menu item is currently selected. And the "items" property specifies the child menu items. + * + * The following example shows how to use CMenu: + *
              + * $this->widget('zii.widgets.CMenu', array(
              + *     'items'=>array(
              + *         // Important: you need to specify url as 'controller/action',
              + *         // not just as 'controller' even if default acion is used.
              + *         array('label'=>'Home', 'url'=>array('site/index')),
              + *         // 'Products' menu item will be selected no matter which tag parameter value is since it's not specified.
              + *         array('label'=>'Products', 'url'=>array('product/index'), 'items'=>array(
              + *             array('label'=>'New Arrivals', 'url'=>array('product/new', 'tag'=>'new')),
              + *             array('label'=>'Most Popular', 'url'=>array('product/index', 'tag'=>'popular')),
              + *         )),
              + *         array('label'=>'Login', 'url'=>array('site/login'), 'visible'=>Yii::app()->user->isGuest),
              + *     ),
              + * ));
              + * 
              + * + * + * @author Jonah Turnquist + * @author Qiang Xue + * @package zii.widgets + * @since 1.1 + */ +class CMenu extends CWidget +{ + /** + * @var array list of menu items. Each menu item is specified as an array of name-value pairs. + * Possible option names include the following: + *
                + *
              • label: string, optional, specifies the menu item label. When {@link encodeLabel} is true, the label + * will be HTML-encoded. If the label is not specified, it defaults to an empty string.
              • + *
              • url: string or array, optional, specifies the URL of the menu item. It is passed to {@link CHtml::normalizeUrl} + * to generate a valid URL. If this is not set, the menu item will be rendered as a span text.
              • + *
              • visible: boolean, optional, whether this menu item is visible. Defaults to true. + * This can be used to control the visibility of menu items based on user permissions.
              • + *
              • items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.
              • + *
              • active: boolean, optional, whether this menu item is in active state (currently selected). + * If a menu item is active and {@link activeClass} is not empty, its CSS class will be appended with {@link activeClass}. + * If this option is not set, the menu item will be set active automatically when the current request + * is triggered by {@link url}. Note that the GET parameters not specified in the 'url' option will be ignored.
              • + *
              • template: string, optional, the template used to render this menu item. + * When this option is set, it will override the global setting {@link itemTemplate}. + * Please see {@link itemTemplate} for more details. This option has been available since version 1.1.1.
              • + *
              • linkOptions: array, optional, additional HTML attributes to be rendered for the link or span tag of the menu item.
              • + *
              • itemOptions: array, optional, additional HTML attributes to be rendered for the container tag of the menu item.
              • + *
              • submenuOptions: array, optional, additional HTML attributes to be rendered for the container of the submenu if this menu item has one. + * When this option is set, the {@link submenuHtmlOptions} property will be ignored for this particular submenu. + * This option has been available since version 1.1.6.
              • + *
              + */ + public $items=array(); + /** + * @var string the template used to render an individual menu item. In this template, + * the token "{menu}" will be replaced with the corresponding menu link or text. + * If this property is not set, each menu will be rendered without any decoration. + * This property will be overridden by the 'template' option set in individual menu items via {@items}. + * @since 1.1.1 + */ + public $itemTemplate; + /** + * @var boolean whether the labels for menu items should be HTML-encoded. Defaults to true. + */ + public $encodeLabel=true; + /** + * @var string the CSS class to be appended to the active menu item. Defaults to 'active'. + * If empty, the CSS class of menu items will not be changed. + */ + public $activeCssClass='active'; + /** + * @var boolean whether to automatically activate items according to whether their route setting + * matches the currently requested route. Defaults to true. + * @since 1.1.3 + */ + public $activateItems=true; + /** + * @var boolean whether to activate parent menu items when one of the corresponding child menu items is active. + * The activated parent menu items will also have its CSS classes appended with {@link activeCssClass}. + * Defaults to false. + */ + public $activateParents=false; + /** + * @var boolean whether to hide empty menu items. An empty menu item is one whose 'url' option is not + * set and which doesn't contain visible child menu items. Defaults to true. + */ + public $hideEmptyItems=true; + /** + * @var array HTML attributes for the menu's root container tag + */ + public $htmlOptions=array(); + /** + * @var array HTML attributes for the submenu's container tag. + */ + public $submenuHtmlOptions=array(); + /** + * @var string the HTML element name that will be used to wrap the label of all menu links. + * For example, if this property is set as 'span', a menu item may be rendered as + * <li><a href="url"><span>label</span></a></li> + * This is useful when implementing menu items using the sliding window technique. + * Defaults to null, meaning no wrapper tag will be generated. + * @since 1.1.4 + */ + public $linkLabelWrapper; + /** + * @var array HTML attributes for the links' wrap element specified in + * {@link linkLabelWrapper}. + * @since 1.1.13 + */ + public $linkLabelWrapperHtmlOptions=array(); + /** + * @var string the CSS class that will be assigned to the first item in the main menu or each submenu. + * Defaults to null, meaning no such CSS class will be assigned. + * @since 1.1.4 + */ + public $firstItemCssClass; + /** + * @var string the CSS class that will be assigned to the last item in the main menu or each submenu. + * Defaults to null, meaning no such CSS class will be assigned. + * @since 1.1.4 + */ + public $lastItemCssClass; + /** + * @var string the CSS class that will be assigned to every item. + * Defaults to null, meaning no such CSS class will be assigned. + * @since 1.1.9 + */ + public $itemCssClass; + + /** + * Initializes the menu widget. + * This method mainly normalizes the {@link items} property. + * If this method is overridden, make sure the parent implementation is invoked. + */ + public function init() + { + $this->htmlOptions['id']=$this->getId(); + $route=$this->getController()->getRoute(); + $this->items=$this->normalizeItems($this->items,$route,$hasActiveChild); + } + + /** + * Calls {@link renderMenu} to render the menu. + */ + public function run() + { + $this->renderMenu($this->items); + } + + /** + * Renders the menu items. + * @param array $items menu items. Each menu item will be an array with at least two elements: 'label' and 'active'. + * It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'. + */ + protected function renderMenu($items) + { + if(count($items)) + { + echo CHtml::openTag('ul',$this->htmlOptions)."\n"; + $this->renderMenuRecursive($items); + echo CHtml::closeTag('ul'); + } + } + + /** + * Recursively renders the menu items. + * @param array $items the menu items to be rendered recursively + */ + protected function renderMenuRecursive($items) + { + $count=0; + $n=count($items); + foreach($items as $item) + { + $count++; + $options=isset($item['itemOptions']) ? $item['itemOptions'] : array(); + $class=array(); + if($item['active'] && $this->activeCssClass!='') + $class[]=$this->activeCssClass; + if($count===1 && $this->firstItemCssClass!==null) + $class[]=$this->firstItemCssClass; + if($count===$n && $this->lastItemCssClass!==null) + $class[]=$this->lastItemCssClass; + if($this->itemCssClass!==null) + $class[]=$this->itemCssClass; + if($class!==array()) + { + if(empty($options['class'])) + $options['class']=implode(' ',$class); + else + $options['class'].=' '.implode(' ',$class); + } + + echo CHtml::openTag('li', $options); + + $menu=$this->renderMenuItem($item); + if(isset($this->itemTemplate) || isset($item['template'])) + { + $template=isset($item['template']) ? $item['template'] : $this->itemTemplate; + echo strtr($template,array('{menu}'=>$menu)); + } + else + echo $menu; + + if(isset($item['items']) && count($item['items'])) + { + echo "\n".CHtml::openTag('ul',isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions)."\n"; + $this->renderMenuRecursive($item['items']); + echo CHtml::closeTag('ul')."\n"; + } + + echo CHtml::closeTag('li')."\n"; + } + } + + /** + * Renders the content of a menu item. + * Note that the container and the sub-menus are not rendered here. + * @param array $item the menu item to be rendered. Please see {@link items} on what data might be in the item. + * @return string + * @since 1.1.6 + */ + protected function renderMenuItem($item) + { + if(isset($item['url'])) + { + $label=$this->linkLabelWrapper===null ? $item['label'] : CHtml::tag($this->linkLabelWrapper, $this->linkLabelWrapperHtmlOptions, $item['label']); + return CHtml::link($label,$item['url'],isset($item['linkOptions']) ? $item['linkOptions'] : array()); + } + else + return CHtml::tag('span',isset($item['linkOptions']) ? $item['linkOptions'] : array(), $item['label']); + } + + /** + * Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item. + * @param array $items the items to be normalized. + * @param string $route the route of the current request. + * @param boolean $active whether there is an active child menu item. + * @return array the normalized menu items + */ + protected function normalizeItems($items,$route,&$active) + { + foreach($items as $i=>$item) + { + if(isset($item['visible']) && !$item['visible']) + { + unset($items[$i]); + continue; + } + if(!isset($item['label'])) + $item['label']=''; + if($this->encodeLabel) + $items[$i]['label']=CHtml::encode($item['label']); + $hasActiveChild=false; + if(isset($item['items'])) + { + $items[$i]['items']=$this->normalizeItems($item['items'],$route,$hasActiveChild); + if(empty($items[$i]['items']) && $this->hideEmptyItems) + { + unset($items[$i]['items']); + if(!isset($item['url'])) + { + unset($items[$i]); + continue; + } + } + } + if(!isset($item['active'])) + { + if($this->activateParents && $hasActiveChild || $this->activateItems && $this->isItemActive($item,$route)) + $active=$items[$i]['active']=true; + else + $items[$i]['active']=false; + } + elseif($item['active']) + $active=true; + } + return array_values($items); + } + + /** + * Checks whether a menu item is active. + * This is done by checking if the currently requested URL is generated by the 'url' option + * of the menu item. Note that the GET parameters not specified in the 'url' option will be ignored. + * @param array $item the menu item to be checked + * @param string $route the route of the current request + * @return boolean whether the menu item is active + */ + protected function isItemActive($item,$route) + { + if(isset($item['url']) && is_array($item['url']) && !strcasecmp(trim($item['url'][0],'/'),$route)) + { + unset($item['url']['#']); + if(count($item['url'])>1) + { + foreach(array_splice($item['url'],1) as $name=>$value) + { + if(!isset($_GET[$name]) || $_GET[$name]!=$value) + return false; + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CPortlet.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CPortlet.php new file mode 100644 index 0000000..fe01be1 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/CPortlet.php @@ -0,0 +1,125 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CPortlet is the base class for portlet widgets. + * + * A portlet displays a fragment of content, usually in terms of a block + * on the side bars of a Web page. + * + * To specify the content of the portlet, override the {@link renderContent} + * method, or insert the content code between the {@link CController::beginWidget} + * and {@link CController::endWidget} calls. For example, + * + *
              + * beginWidget('zii.widgets.CPortlet'); ?>
              + *     ...insert content here...
              + * endWidget(); ?>
              + * 
              + * + * A portlet also has an optional {@link title}. One may also override {@link renderDecoration} + * to further customize the decorative display of a portlet (e.g. adding min/max buttons). + * + * @author Qiang Xue + * @package zii.widgets + * @since 1.1 + */ +class CPortlet extends CWidget +{ + /** + * @var string the tag name for the portlet container tag. Defaults to 'div'. + */ + public $tagName='div'; + /** + * @var array the HTML attributes for the portlet container tag. + */ + public $htmlOptions=array('class'=>'portlet'); + /** + * @var string the title of the portlet. Defaults to null. + * When this is not set, Decoration will not be displayed. + * Note that the title will not be HTML-encoded when rendering. + */ + public $title; + /** + * @var string the CSS class for the decoration container tag. Defaults to 'portlet-decoration'. + */ + public $decorationCssClass='portlet-decoration'; + /** + * @var string the CSS class for the portlet title tag. Defaults to 'portlet-title'. + */ + public $titleCssClass='portlet-title'; + /** + * @var string the CSS class for the content container tag. Defaults to 'portlet-content'. + */ + public $contentCssClass='portlet-content'; + /** + * @var boolean whether to hide the portlet when the body content is empty. Defaults to true. + * @since 1.1.4 + */ + public $hideOnEmpty=true; + + private $_openTag; + + /** + * Initializes the widget. + * This renders the open tags needed by the portlet. + * It also renders the decoration, if any. + */ + public function init() + { + ob_start(); + ob_implicit_flush(false); + + $this->htmlOptions['id']=$this->getId(); + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + $this->renderDecoration(); + echo "
              contentCssClass}\">\n"; + + $this->_openTag=ob_get_contents(); + ob_clean(); + } + + /** + * Renders the content of the portlet. + */ + public function run() + { + $this->renderContent(); + $content=ob_get_clean(); + if($this->hideOnEmpty && trim($content)==='') + return; + echo $this->_openTag; + echo $content; + echo "
              \n"; + echo CHtml::closeTag($this->tagName); + } + + /** + * Renders the decoration for the portlet. + * The default implementation will render the title if it is set. + */ + protected function renderDecoration() + { + if($this->title!==null) + { + echo "
              decorationCssClass}\">\n"; + echo "
              titleCssClass}\">{$this->title}
              \n"; + echo "
              \n"; + } + } + + /** + * Renders the content of the portlet. + * Child classes should override this method to render the actual content. + */ + protected function renderContent() + { + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/detailview/styles.css b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/detailview/styles.css new file mode 100644 index 0000000..e1d1dc4 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/detailview/styles.css @@ -0,0 +1,44 @@ +table.detail-view .null +{ + color: pink; +} + +table.detail-view +{ + background: white; + border-collapse: collapse; + width: 100%; + margin: 0; +} + +table.detail-view th, table.detail-view td +{ + font-size: 0.9em; + border: 1px white solid; + padding: 0.3em 0.6em; + vertical-align: top; +} + +table.detail-view th +{ + text-align: right; + width: 160px; +} + +table.detail-view tr.odd +{ + background:#E5F1F4; +} + +table.detail-view tr.even +{ + background:#F8F8F8; +} + +table.detail-view tr.odd th +{ +} + +table.detail-view tr.even th +{ +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/bg.gif b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..428398973e1a8a6a1129d9332da6714e59bedba4 GIT binary patch literal 243 zcmZ?wbhEHbWMeR5IKlt||Ns9Fn|mU0@#)m1XEK+c^_h9pch)ig*~bFs91EU%JYxQd z=mjU^7M;pmaW-ewx%@Tfi`HEz-EgsD1pFZrjzSo!1+8Tx;5Kt##K8 zpn+h6L4@K@7DfgJ83r8?2V^G$YrzAxzKG1Mj9F{fJlz+r6JFwb_s5d=LGRrUD5QAQ zNc8tDnRFnBZ{CHrl2a?9#BZ!gI2~HCzjK3xqn`Y^jOMDdVT&(5-4yZXZ_&=1Ypz<& pbz11_%i7%H?(X8^=xAqWZEay;YHDPpudkz{si~%>tgOgj4FL3OZcYFI literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/delete.png b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..dc4c12aa002a7d5249c3560c05be12a66e60c6d9 GIT binary patch literal 715 zcmV;+0yO=JP)+^$SLwjJnFwXOPfA8TCw4_)pUQQ;HS3^7i z7H0}_uc%d}Rj-5(ejcouZ_0EI%~Vm6z7Xc&fy|Ad!e+ctdPe^e@!q1p2iO@jM^jr@#YTkC9v2rxgx+}YX5 z5ws*Q2u|R0|BDm`93oEPAWr~3-Ly5?fO0dZwkZHD??(Itfb?gclg@a$(snB5MBtN3KkjCCyw=EAt!5hxIdrO x^-~#ylFUuylGxt%nCr{|kh#TLI-Ons&tElxCVrm3f13aR002ovPDHLkV1klJMTh_Z literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/down.gif b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..a4933b884179f1c01c101f86f473287367a5c0e9 GIT binary patch literal 55 zcmZ?wbhEHbWM^Pun8*ME|G@yrQ2fcl$iTqFpaT*G$ulr + * @link http://www.yiiframework.com/ + * @copyright 2008-2010 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +(function ($) { + var selectCheckedRows, methods, + yiiXHR={}, + gridSettings = []; + /** + * 1. Selects rows that have checkbox checked (only checkbox that is connected with selecting a row) + * 2. Check if "check all" need to be checked/unchecked + * @return object the jQuery object + */ + selectCheckedRows = function (gridId) { + var settings = gridSettings[gridId], + table = $('#' + gridId).find('.' + settings.tableClass); + + table.children('tbody').find('input.select-on-check').filter(':checked').each(function () { + $(this).closest('tr').addClass('selected'); + }); + + table.children('thead').find('th input').filter('[type="checkbox"]').each(function () { + var name = this.name.substring(0, this.name.length - 4) + '[]', //.. remove '_all' and add '[]'' + $checks = $("input[name='" + name + "']", table); + this.checked = $checks.length > 0 && $checks.length === $checks.filter(':checked').length; + }); + return this; + }; + + methods = { + /** + * yiiGridView set function. + * @param options map settings for the grid view. Available options are as follows: + * - ajaxUpdate: array, IDs of the containers whose content may be updated by ajax response + * - ajaxVar: string, the name of the request variable indicating the ID of the element triggering the AJAX request + * - ajaxType: string, the type (GET or POST) of the AJAX request + * - pagerClass: string, the CSS class for the pager container + * - tableClass: string, the CSS class for the table + * - selectableRows: integer, the number of rows that can be selected + * - updateSelector: string, the selector for choosing which elements can trigger ajax requests + * - beforeAjaxUpdate: function, the function to be called before ajax request is sent + * - afterAjaxUpdate: function, the function to be called after ajax response is received + * - ajaxUpdateError: function, the function to be called if an ajax error occurs + * - selectionChanged: function, the function to be called after the row selection is changed + * @return object the jQuery object + */ + init: function (options) { + var settings = $.extend({ + ajaxUpdate: [], + ajaxVar: 'ajax', + ajaxType: 'GET', + pagerClass: 'pager', + loadingClass: 'loading', + filterClass: 'filters', + tableClass: 'items', + selectableRows: 1 + // updateSelector: '#id .pager a, '#id .grid thead th a', + // beforeAjaxUpdate: function (id) {}, + // afterAjaxUpdate: function (id, data) {}, + // selectionChanged: function (id) {}, + // url: 'ajax request URL' + }, options || {}); + + settings.tableClass = settings.tableClass.replace(/\s+/g, '.'); + + return this.each(function () { + var eventType, + $grid = $(this), + id = $grid.attr('id'), + pagerSelector = '#' + id + ' .' + settings.pagerClass.replace(/\s+/g, '.') + ' a', + sortSelector = '#' + id + ' .' + settings.tableClass + ' thead th a.sort-link', + inputSelector = '#' + id + ' .' + settings.filterClass + ' input, ' + '#' + id + ' .' + settings.filterClass + ' select'; + + settings.updateSelector = settings.updateSelector + .replace('{page}', pagerSelector) + .replace('{sort}', sortSelector); + settings.filterSelector = settings.filterSelector + .replace('{filter}', inputSelector); + + gridSettings[id] = settings; + + if (settings.ajaxUpdate.length > 0) { + $(document).on('click.yiiGridView', settings.updateSelector, function () { + // Check to see if History.js is enabled for our Browser + if (settings.enableHistory && window.History.enabled) { + // Ajaxify this link + var url = $(this).attr('href').split('?'), + params = $.deparam.querystring('?'+ (url[1] || '')); + + delete params[settings.ajaxVar]; + window.History.pushState(null, document.title, decodeURIComponent($.param.querystring(url[0], params))); + } else { + $('#' + id).yiiGridView('update', {url: $(this).attr('href')}); + } + return false; + }); + } + + $(document).on('change.yiiGridView keydown.yiiGridView', settings.filterSelector, function (event) { + if (event.type === 'keydown') { + if( event.keyCode !== 13) { + return; // only react to enter key + } else { + eventType = 'keydown'; + } + } else { + // prevent processing for both keydown and change events + if (eventType === 'keydown') { + eventType = ''; + return; + } + } + var data = $(settings.filterSelector).serialize(); + if (settings.pageVar !== undefined) { + data += '&' + settings.pageVar + '=1'; + } + if (settings.enableHistory && settings.ajaxUpdate !== false && window.History.enabled) { + // Ajaxify this link + var url = $('#' + id).yiiGridView('getUrl'), + params = $.deparam.querystring($.param.querystring(url, data)); + + delete params[settings.ajaxVar]; + window.History.pushState(null, document.title, decodeURIComponent($.param.querystring(url.substr(0, url.indexOf('?')), params))); + } else { + $('#' + id).yiiGridView('update', {data: data}); + } + }); + + if (settings.enableHistory && settings.ajaxUpdate !== false && window.History.enabled) { + $(window).bind('statechange', function() { // Note: We are using statechange instead of popstate + var State = window.History.getState(); // Note: We are using History.getState() instead of event.state + $('#' + id).yiiGridView('update', {url: State.url}); + }); + } + + if (settings.selectableRows > 0) { + selectCheckedRows(this.id); + $(document).on('click.yiiGridView', '#' + id + ' .' + settings.tableClass + ' > tbody > tr', function (e) { + var $currentGrid, $row, isRowSelected, $checks, + $target = $(e.target); + + if ($target.closest('td').is('.empty,.button-column') || (e.target.type === 'checkbox' && !$target.hasClass('select-on-check'))) { + return; + } + + $row = $(this); + $currentGrid = $('#' + id); + $checks = $('input.select-on-check', $currentGrid); + isRowSelected = $row.toggleClass('selected').hasClass('selected'); + + if (settings.selectableRows === 1) { + $row.siblings().removeClass('selected'); + $checks.prop('checked', false); + } + $('input.select-on-check', $row).prop('checked', isRowSelected); + $("input.select-on-check-all", $currentGrid).prop('checked', $checks.length === $checks.filter(':checked').length); + + if (settings.selectionChanged !== undefined) { + settings.selectionChanged(id); + } + }); + if (settings.selectableRows > 1) { + $(document).on('click.yiiGridView', '#' + id + ' .select-on-check-all', function () { + var $currentGrid = $('#' + id), + $checks = $('input.select-on-check', $currentGrid), + $checksAll = $('input.select-on-check-all', $currentGrid), + $rows = $currentGrid.find('.' + settings.tableClass).children('tbody').children(); + if (this.checked) { + $rows.addClass('selected'); + $checks.prop('checked', true); + $checksAll.prop('checked', true); + } else { + $rows.removeClass('selected'); + $checks.prop('checked', false); + $checksAll.prop('checked', false); + } + if (settings.selectionChanged !== undefined) { + settings.selectionChanged(id); + } + }); + } + } else { + $(document).on('click.yiiGridView', '#' + id + ' .select-on-check', false); + } + }); + }, + + /** + * Returns the key value for the specified row + * @param row integer the row number (zero-based index) + * @return string the key value + */ + getKey: function (row) { + return this.children('.keys').children('span').eq(row).text(); + }, + + /** + * Returns the URL that generates the grid view content. + * @return string the URL that generates the grid view content. + */ + getUrl: function () { + var sUrl = gridSettings[this.attr('id')].url; + return sUrl || this.children('.keys').attr('title'); + }, + + /** + * Returns the jQuery collection of the cells in the specified row. + * @param row integer the row number (zero-based index) + * @return jQuery the jQuery collection of the cells in the specified row. + */ + getRow: function (row) { + var sClass = gridSettings[this.attr('id')].tableClass; + return this.find('.' + sClass).children('tbody').children('tr').eq(row).children(); + }, + + /** + * Returns the jQuery collection of the cells in the specified column. + * @param column integer the column number (zero-based index) + * @return jQuery the jQuery collection of the cells in the specified column. + */ + getColumn: function (column) { + var sClass = gridSettings[this.attr('id')].tableClass; + return this.find('.' + sClass).children('tbody').children('tr').children('td:nth-child(' + (column + 1) + ')'); + }, + + /** + * Performs an AJAX-based update of the grid view contents. + * @param options map the AJAX request options (see jQuery.ajax API manual). By default, + * the URL to be requested is the one that generates the current content of the grid view. + * @return object the jQuery object + */ + update: function (options) { + var customError; + if (options && options.error !== undefined) { + customError = options.error; + delete options.error; + } + + return this.each(function () { + var $form, + $grid = $(this), + id = $grid.attr('id'), + settings = gridSettings[id]; + + options = $.extend({ + type: settings.ajaxType, + url: $grid.yiiGridView('getUrl'), + success: function (data) { + var $data = $('
              ' + data + '
              '); + $.each(settings.ajaxUpdate, function (i, el) { + var updateId = '#' + el; + $(updateId).replaceWith($(updateId, $data)); + }); + if (settings.afterAjaxUpdate !== undefined) { + settings.afterAjaxUpdate(id, data); + } + if (settings.selectableRows > 0) { + selectCheckedRows(id); + } + }, + complete: function () { + yiiXHR[id] = null; + $grid.removeClass(settings.loadingClass); + }, + error: function (XHR, textStatus, errorThrown) { + var ret, err; + if (XHR.readyState === 0 || XHR.status === 0) { + return; + } + if (customError !== undefined) { + ret = customError(XHR); + if (ret !== undefined && !ret) { + return; + } + } + switch (textStatus) { + case 'timeout': + err = 'The request timed out!'; + break; + case 'parsererror': + err = 'Parser error!'; + break; + case 'error': + if (XHR.status && !/^\s*$/.test(XHR.status)) { + err = 'Error ' + XHR.status; + } else { + err = 'Error'; + } + if (XHR.responseText && !/^\s*$/.test(XHR.responseText)) { + err = err + ': ' + XHR.responseText; + } + break; + } + + if (settings.ajaxUpdateError !== undefined) { + settings.ajaxUpdateError(XHR, textStatus, errorThrown, err); + } else if (err) { + alert(err); + } + } + }, options || {}); + if (options.type === 'GET') { + if (options.data !== undefined) { + options.url = $.param.querystring(options.url, options.data); + options.data = {}; + } + } else { + if (options.data === undefined) { + options.data = $(settings.filterSelector).serialize(); + } + } + if(yiiXHR[id] != null){ + yiiXHR[id].abort(); + } + //class must be added after yiiXHR.abort otherwise ajax.error will remove it + $grid.addClass(settings.loadingClass); + + if (settings.ajaxUpdate !== false) { + options.url = $.param.querystring(options.url, settings.ajaxVar + '=' + id); + if (settings.beforeAjaxUpdate !== undefined) { + settings.beforeAjaxUpdate(id, options); + } + yiiXHR[id] = $.ajax(options); + } else { // non-ajax mode + if (options.type === 'GET') { + window.location.href = options.url; + } else { // POST mode + $form = $('
              ').appendTo('body'); + if (options.data === undefined) { + options.data = {}; + } + + if (options.data.returnUrl === undefined) { + options.data.returnUrl = window.location.href; + } + + $.each(options.data, function (name, value) { + $form.append($('').attr('name', name).val(value)); + }); + $form.submit(); + } + } + }); + }, + + /** + * Returns the key values of the currently selected rows. + * @return array the key values of the currently selected rows. + */ + getSelection: function () { + var settings = gridSettings[this.attr('id')], + keys = this.find('.keys span'), + selection = []; + this.find('.' + settings.tableClass).children('tbody').children().each(function (i) { + if ($(this).hasClass('selected')) { + selection.push(keys.eq(i).text()); + } + }); + return selection; + }, + + /** + * Returns the key values of the currently checked rows. + * @param column_id string the ID of the column + * @return array the key values of the currently checked rows. + */ + getChecked: function (column_id) { + var settings = gridSettings[this.attr('id')], + keys = this.find('.keys span'), + checked = []; + if (column_id.substring(column_id.length - 2) !== '[]') { + column_id = column_id + '[]'; + } + this.find('.' + settings.tableClass).children('tbody').children('tr').children('td').children('input[name="' + column_id + '"]').each(function (i) { + if (this.checked) { + checked.push(keys.eq(i).text()); + } + }); + return checked; + } + + }; + + $.fn.yiiGridView = function (method) { + if (methods[method]) { + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || !method) { + return methods.init.apply(this, arguments); + } else { + $.error('Method ' + method + ' does not exist on jQuery.yiiGridView'); + return false; + } + }; + +/****************************************************************************** + *** DEPRECATED METHODS + *** used before Yii 1.1.9 + ******************************************************************************/ + $.fn.yiiGridView.settings = gridSettings; + /** + * Returns the key value for the specified row + * @param id string the ID of the grid view container + * @param row integer the row number (zero-based index) + * @return string the key value + */ + $.fn.yiiGridView.getKey = function (id, row) { + return $('#' + id).yiiGridView('getKey', row); + }; + + /** + * Returns the URL that generates the grid view content. + * @param id string the ID of the grid view container + * @return string the URL that generates the grid view content. + */ + $.fn.yiiGridView.getUrl = function (id) { + return $('#' + id).yiiGridView('getUrl'); + }; + + /** + * Returns the jQuery collection of the cells in the specified row. + * @param id string the ID of the grid view container + * @param row integer the row number (zero-based index) + * @return jQuery the jQuery collection of the cells in the specified row. + */ + $.fn.yiiGridView.getRow = function (id, row) { + return $('#' + id).yiiGridView('getRow', row); + }; + + /** + * Returns the jQuery collection of the cells in the specified column. + * @param id string the ID of the grid view container + * @param column integer the column number (zero-based index) + * @return jQuery the jQuery collection of the cells in the specified column. + */ + $.fn.yiiGridView.getColumn = function (id, column) { + return $('#' + id).yiiGridView('getColumn', column); + }; + + /** + * Performs an AJAX-based update of the grid view contents. + * @param id string the ID of the grid view container + * @param options map the AJAX request options (see jQuery.ajax API manual). By default, + * the URL to be requested is the one that generates the current content of the grid view. + */ + $.fn.yiiGridView.update = function (id, options) { + $('#' + id).yiiGridView('update', options); + }; + + /** + * Returns the key values of the currently selected rows. + * @param id string the ID of the grid view container + * @return array the key values of the currently selected rows. + */ + $.fn.yiiGridView.getSelection = function (id) { + return $('#' + id).yiiGridView('getSelection'); + }; + + /** + * Returns the key values of the currently checked rows. + * @param id string the ID of the grid view container + * @param column_id string the ID of the column + * @return array the key values of the currently checked rows. + */ + $.fn.yiiGridView.getChecked = function (id, column_id) { + return $('#' + id).yiiGridView('getChecked', column_id); + }; +})(jQuery); diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/loading.gif b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 zcma*odr(tX9tZI2z31lM+(&YVk%mZ}5P~KlG2s=WSbGzm0!x7^P##Mnh7t-jP!X0Q zk_SQ}Po-L1tlDK;6l?(>v)e5ZBQx4|Y-Q?nr@Px3?9h(3ZWr3^tj=`TP57gKr87N$ zp2wWee1GRRCwo_xahnw)5cxNPJbCg2L6DV|6`#+yw6v6!mDS$f9-JvFD^n;GQ&UrZ zzh5jCkByB101O60U0q#p_1BM>Cv-vP?&s4@g_((4_1L=L$(a91)0=J91Gas#R{McE znYG^9*0A5YZ>#;~+Wkn(W5B0^yELIYLP!K}mB~<)AM@1&nqekynuaEGqPrzoH|KodRXJy)%+w_fu3nE5>@Bd_b zqC$EQ;{c`T&?EsNO|igL9gC7Ygxv?aQUEXMq?~>wg{EyW;VcJ37CUF#HjrT=KQO_* zS>M9yydXk18D(+QDJ1>r);Lav_uYKp$T?4vr{Q$lTo&pKv^?(>L-)G2*lwH!Ah7k? z7oH<8h-(KTKt5V6$8gF)C7Io&P5=SjTh)=zV=E2EUhQZP##L8S{d%UK>>+y82>+FV+#^BzW7u3F)Bb>=lYQ%%j`F>ASe zo*cw@V#u6T`A2He;70mR(V&iV&-7{qP~=SRf&jm9-T{*ZeZ}$rd0#6c&fLG^xJcf5 z+p<`wJYgW+_s*V{uI$nMB;%8`S_3>PfGOj3Rq}@Cx^+j?rk92fANSFDBYnOqQ>Vdj z)(|$AhP4t&Lb=Gvo2#3Gl%9<=Gv`Mz?Po@P4iLF!x}GUWJICDlFk-hS^Whyh7x~VH z@0vD1>HYD4&e+~yzS*-sFR{9`{QEEZO1zg7>R&7cHts-6j!xHVdA8eI+ZlVzd%`es zJT@$#GX(gvCJ1oJN%yLBK}{V=V;seo;!w|Yte!W1%5qLNFWqvZW>h&IiH+oPT=b@E zPhGzv5=(Un*X>v`>%8h_nj^NdYcE6NHS_ifkCV$*D)Tqrbu`s;<=t<4 zAHNqNV?6(g<1PY-w@#I-WYFViz?9TrkMr)u0g`O`u|>T;k|2sV*YF^punvT;$SuTy{j3Gv)yqD!R_CF>yR)MzmmYS5v+~R zXAdD%ng9?df;wd8GxR#%3O+gz};Vo;)sK%Bj-q>Oq%R7JU-KD?vYu>#2UjaDo z&8$>5xW~?KPD_#XFToU1hIb*VOMidUr6iYiO0N|i-7s`T8!cFT`rN!^1Pt78J93i6 z5HI1wIM$94m{3SLDvISDe6$ZG1;eq_D9RTaaC>=cO{@Bs>$IlPCPJJ$h$)-3vzNUQ6OsN#_zWxey!_9%hxwH2_dEJi=yY|1c7nDm2_Lm!Cof8-R_+9UkS zcBE(o47yE)oMR(Q=dp1a2wTX5KvvGyLqlWTa7V&!A*|w|)ax~1_~aJ0=_Lilg*0iQk7#ZD EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/styles.css b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/styles.css new file mode 100644 index 0000000..fe5538e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/styles.css @@ -0,0 +1,125 @@ +.grid-view-loading +{ + background:url(loading.gif) no-repeat; +} + +.grid-view +{ + padding: 15px 0; +} + +.grid-view table.items +{ + background: white; + border-collapse: collapse; + width: 100%; + border: 1px #D0E3EF solid; +} + +.grid-view table.items th, .grid-view table.items td +{ + font-size: 0.9em; + border: 1px white solid; + padding: 0.3em; +} + +.grid-view table.items th +{ + color: white; + background: url("bg.gif") repeat-x scroll left top white; + text-align: center; +} + +.grid-view table.items th a +{ + color: #EEE; + font-weight: bold; + text-decoration: none; +} + +.grid-view table.items th a:hover +{ + color: #FFF; +} + +.grid-view table.items th a.asc +{ + background:url(up.gif) right center no-repeat; + padding-right: 10px; +} + +.grid-view table.items th a.desc +{ + background:url(down.gif) right center no-repeat; + padding-right: 10px; +} + +.grid-view table.items tr.even +{ + background: #F8F8F8; +} + +.grid-view table.items tr.odd +{ + background: #E5F1F4; +} + +.grid-view table.items tr.selected +{ + background: #BCE774; +} + +.grid-view table.items tr:hover.selected +{ + background: #CCFF66; +} + +.grid-view table.items tbody tr:hover +{ + background: #ECFBD4; +} + +.grid-view .link-column img +{ + border: 0; +} + +.grid-view .button-column +{ + text-align: center; + width: 60px; +} + +.grid-view .button-column img +{ + border: 0; +} + +.grid-view .checkbox-column +{ + width: 15px; +} + +.grid-view .summary +{ + margin: 0 0 5px 0; + text-align: right; +} + +.grid-view .pager +{ + margin: 5px 0 0 0; + text-align: right; +} + +.grid-view .empty +{ + font-style: italic; +} + +.grid-view .filters input, +.grid-view .filters select +{ + width: 100%; + border: 1px solid #ccc; +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/up.gif b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/up.gif new file mode 100644 index 0000000000000000000000000000000000000000..890b03882768a83dcee5a2b0afbc69767d3c4eb3 GIT binary patch literal 54 ycmZ?wbhEHbWM^Pun8*ME|G@yrQ2fcl$iTqFpaT*G$ulsqPf6rleVUJ(!5RR0;|yp3 literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/update.png b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/update.png new file mode 100644 index 0000000000000000000000000000000000000000..438b7c17574999f9e256bf4d024112f016da713e GIT binary patch literal 713 zcmV;)0yh1LP)QXX1S+Tidn^zr1ETlddPzzmBFX?M z?8TR)Ahw7okwT_ztqt9s)-AS~o&P=t*Jh|QT;R^!bIv_y?&YwCLZL7ekH<$DV@&{D zgy8#reZoA?t5vJjdyeBw_w@8Q0toqh{%|Ulnn)xPX<8g2M8R=^A0$aSST2_@0=O9n zkn;f=X~Qr;4*#RB?ZgYjlgVVfp`qc(x&Xl^A_PJB$DLz5SWFBweA@=CjKmVc6Uqe= zijX}+$I{FsJfC6f@HxnhNw_3L94{geg->~Tik3j(>lZj?1(n$eScM!0F5Lj*dDOu` zAlFDq0xv=!_uRrfd|rmQ_dMjITJl-eNd2 zh7{|9)4vbtW2e#BuD}b$X5k2iZbJW6#pAhgWLKVGRZubcViZ5EJYp^|aN!zS2lv!F zh(_QzhNPUpyX6O1vKP>?WhZ6j;7JDNKHY($D4??f$F}Q*3x9V2fTt(_<0Zb^Ic(n4 z3)gkgk=}*2rY`IsIECg7jYPIUK&@5-V@!+e!0}8d@r~$j-T}k4ptNj5N^HT2!RzSj z9)f9^!8+44VcWJtr}pW3iS)}@Eari&s^~4ghASlSS!zS3{Uo|uccVsR#&H3e0A1Jb zli2ingyo{P`2N)lEcGE+Sw)A*kWr4Ki^!H^foCizjhvxr+8eqDW1XFyzfs5KD_0Ml zJu@=@@%gRA%C`?iO)D46T4kkFD$*#e5UE(AiK?nI*=%+@LI@(%3|-}=)a{DYC-HWR v;u=*Sjt(DQ{UUL)EW6bFY$lUgL!2c{ZT|)00000NkvXXu0mjfE4N80 literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/view.png b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/gridview/view.png new file mode 100644 index 0000000000000000000000000000000000000000..cadbec3fcce1a9df2751c9423cc05192ae9efb57 GIT binary patch literal 803 zcmV+;1Kj+HP)r{${MHR^rXpL0qKXn36@-W(RA3YsMExwtAd0A>faq7zKYtoQN`yv{ zB@kjnMx+s{r8G>Ek*UKuH}Bkbzj}CaCQ#?)-pl*)oO7Os^InEc1cSjQS(dMeqF4+- z!@nWwx}J!|V*SZvvdic58C+m)Zmu*dE9;5F;V3Z-1OI~{2>ffa*$yl(FB^eC-~}UR zC%Nvm+wCQaqCnF$2o@?d(}ce;O_M(^mkVTen#>etu~-BGqYWfU0*P@V6Eh${Ac79f zP&tvGGnN*X05}-U#Kl1%5u#XVF@&RwNU91PwoJ&@92llXA{rOitThb+cP2&dV3q7x zU0cMfFAp%aFa#Y*QAoN3N(cL@kK*l2H>QF^s4Z&chTBHq z?Laqlq*5u!wj7Gl0)x)!vhZXWW5^I?MB`zY08d9%RYvuU1i-VmW-$1?HTbbOj&NiN zx!HwKHexU}0innO=ELJS=e~ zoNml7O{3@CRV1`^>?u2r)P_c#B}^heqT4&n#>U2Ux7(fQ?d`?z;Acp=b?E8u!sxd_ zWLRaaC4NJeT{z#?jiT&IBvT5d6@TgVdS8RUIy*bd3kwVD{eC~nD!iDSh~dt;KG^aV z1Q!GFsp002ovPDHLkV1igha4P@+ literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/down.gif b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..a4933b884179f1c01c101f86f473287367a5c0e9 GIT binary patch literal 55 zcmZ?wbhEHbWM^Pun8*ME|G@yrQ2fcl$iTqFpaT*G$ulr + * @link http://www.yiiframework.com/ + * @copyright 2008-2010 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +;(function($) { + var yiiXHR = {}; + /** + * yiiListView set function. + * @param options map settings for the list view. Availablel options are as follows: + * - ajaxUpdate: array, IDs of the containers whose content may be updated by ajax response + * - ajaxVar: string, the name of the request variable indicating the ID of the element triggering the AJAX request + * - ajaxType: string, the type (GET or POST) of the AJAX request + * - pagerClass: string, the CSS class for the pager container + * - sorterClass: string, the CSS class for the sorter container + * - updateSelector: string, the selector for choosing which elements can trigger ajax requests + * - beforeAjaxUpdate: function, the function to be called before ajax request is sent + * - afterAjaxUpdate: function, the function to be called after ajax response is received + */ + $.fn.yiiListView = function(options) { + return this.each(function(){ + var settings = $.extend({}, $.fn.yiiListView.defaults, options || {}), + $this = $(this), + id = $this.attr('id'); + + if(settings.updateSelector == undefined) { + settings.updateSelector = '#'+id+' .'+settings.pagerClass.replace(/\s+/g,'.')+' a, #'+id+' .'+settings.sorterClass.replace(/\s+/g,'.')+' a'; + } + $.fn.yiiListView.settings[id] = settings; + + if(settings.ajaxUpdate.length > 0) { + $(document).on('click.yiiListView', settings.updateSelector,function(){ + if(settings.enableHistory && window.History.enabled) { + var url = $(this).attr('href').split('?'), + params = $.deparam.querystring('?'+ (url[1] || '')); + + delete params[settings.ajaxVar]; + window.History.pushState(null, document.title, decodeURIComponent($.param.querystring(url[0], params))); + } else { + $.fn.yiiListView.update(id, {url: $(this).attr('href')}); + } + return false; + }); + + if(settings.enableHistory && window.History.enabled) { + $(window).bind('statechange', function() { // Note: We are using statechange instead of popstate + var State = window.History.getState(); // Note: We are using History.getState() instead of event.state + $.fn.yiiListView.update(id, {url: State.url}); + }); + } + } + }); + }; + + $.fn.yiiListView.defaults = { + ajaxUpdate: [], + ajaxVar: 'ajax', + ajaxType: 'GET', + pagerClass: 'pager', + loadingClass: 'loading', + sorterClass: 'sorter' + // updateSelector: '#id .pager a, '#id .sort a', + // beforeAjaxUpdate: function(id) {}, + // afterAjaxUpdate: function(id, data) {}, + // url: 'ajax request URL' + }; + + $.fn.yiiListView.settings = {}; + + /** + * Returns the key value for the specified row + * @param id string the ID of the list view container + * @param index integer the zero-based index of the data item + * @return string the key value + */ + $.fn.yiiListView.getKey = function(id, index) { + return $('#'+id+' > div.keys > span:eq('+index+')').text(); + }; + + /** + * Returns the URL that generates the list view content. + * @param id string the ID of the list view container + * @return string the URL that generates the list view content. + */ + $.fn.yiiListView.getUrl = function(id) { + var settings = $.fn.yiiListView.settings[id]; + return settings.url || $('#'+id+' > div.keys').attr('title'); + }; + + /** + * Performs an AJAX-based update of the list view contents. + * @param id string the ID of the list view container + * @param options map the AJAX request options (see jQuery.ajax API manual). By default, + * the URL to be requested is the one that generates the current content of the list view. + */ + $.fn.yiiListView.update = function(id, options) { + var customError, + settings = $.fn.yiiListView.settings[id]; + + if (options && options.error !== undefined) { + customError = options.error; + delete options.error; + } + + options = $.extend({ + type: settings.ajaxType, + url: $.fn.yiiListView.getUrl(id), + success: function(data,status) { + $.each(settings.ajaxUpdate, function(i,v) { + var id='#'+v; + $(id).replaceWith($(id,'
              '+data+'
              ')); + }); + if(settings.afterAjaxUpdate != undefined) + settings.afterAjaxUpdate(id, data); + }, + complete: function() { + $('#'+id).removeClass(settings.loadingClass); + yiiXHR[id] = null; + }, + error: function(XHR, textStatus, errorThrown) { + var ret, err; + if (XHR.readyState === 0 || XHR.status === 0) { + return; + } + if (customError !== undefined) { + ret = customError(XHR); + if (ret !== undefined && !ret) { + return; + } + } + switch (textStatus) { + case 'timeout': + err = 'The request timed out!'; + break; + case 'parsererror': + err = 'Parser error!'; + break; + case 'error': + if (XHR.status && !/^\s*$/.test(XHR.status)) { + err = 'Error ' + XHR.status; + } else { + err = 'Error'; + } + if (XHR.responseText && !/^\s*$/.test(XHR.responseText)) { + err = err + ': ' + XHR.responseText; + } + break; + } + + if (settings.ajaxUpdateError !== undefined) { + settings.ajaxUpdateError(XHR, textStatus, errorThrown, err); + } else if (err) { + alert(err); + } + } + }, options || {}); + + if(options.data!=undefined && options.type=='GET') { + options.url = $.param.querystring(options.url, options.data); + options.data = {}; + } + options.url = $.param.querystring(options.url, settings.ajaxVar+'='+id); + + if(yiiXHR[id] != null) { + yiiXHR[id].abort(); + } + + $('#'+id).addClass(settings.loadingClass); + + if(settings.beforeAjaxUpdate != undefined) + settings.beforeAjaxUpdate(id); + yiiXHR[id] = $.ajax(options); + }; + +})(jQuery); diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/loading.gif b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 zcma*odr(tX9tZI2z31lM+(&YVk%mZ}5P~KlG2s=WSbGzm0!x7^P##Mnh7t-jP!X0Q zk_SQ}Po-L1tlDK;6l?(>v)e5ZBQx4|Y-Q?nr@Px3?9h(3ZWr3^tj=`TP57gKr87N$ zp2wWee1GRRCwo_xahnw)5cxNPJbCg2L6DV|6`#+yw6v6!mDS$f9-JvFD^n;GQ&UrZ zzh5jCkByB101O60U0q#p_1BM>Cv-vP?&s4@g_((4_1L=L$(a91)0=J91Gas#R{McE znYG^9*0A5YZ>#;~+Wkn(W5B0^yELIYLP!K}mB~<)AM@1&nqekynuaEGqPrzoH|KodRXJy)%+w_fu3nE5>@Bd_b zqC$EQ;{c`T&?EsNO|igL9gC7Ygxv?aQUEXMq?~>wg{EyW;VcJ37CUF#HjrT=KQO_* zS>M9yydXk18D(+QDJ1>r);Lav_uYKp$T?4vr{Q$lTo&pKv^?(>L-)G2*lwH!Ah7k? z7oH<8h-(KTKt5V6$8gF)C7Io&P5=SjTh)=zV=E2EUhQZP##L8S{d%UK>>+y82>+FV+#^BzW7u3F)Bb>=lYQ%%j`F>ASe zo*cw@V#u6T`A2He;70mR(V&iV&-7{qP~=SRf&jm9-T{*ZeZ}$rd0#6c&fLG^xJcf5 z+p<`wJYgW+_s*V{uI$nMB;%8`S_3>PfGOj3Rq}@Cx^+j?rk92fANSFDBYnOqQ>Vdj z)(|$AhP4t&Lb=Gvo2#3Gl%9<=Gv`Mz?Po@P4iLF!x}GUWJICDlFk-hS^Whyh7x~VH z@0vD1>HYD4&e+~yzS*-sFR{9`{QEEZO1zg7>R&7cHts-6j!xHVdA8eI+ZlVzd%`es zJT@$#GX(gvCJ1oJN%yLBK}{V=V;seo;!w|Yte!W1%5qLNFWqvZW>h&IiH+oPT=b@E zPhGzv5=(Un*X>v`>%8h_nj^NdYcE6NHS_ifkCV$*D)Tqrbu`s;<=t<4 zAHNqNV?6(g<1PY-w@#I-WYFViz?9TrkMr)u0g`O`u|>T;k|2sV*YF^punvT;$SuTy{j3Gv)yqD!R_CF>yR)MzmmYS5v+~R zXAdD%ng9?df;wd8GxR#%3O+gz};Vo;)sK%Bj-q>Oq%R7JU-KD?vYu>#2UjaDo z&8$>5xW~?KPD_#XFToU1hIb*VOMidUr6iYiO0N|i-7s`T8!cFT`rN!^1Pt78J93i6 z5HI1wIM$94m{3SLDvISDe6$ZG1;eq_D9RTaaC>=cO{@Bs>$IlPCPJJ$h$)-3vzNUQ6OsN#_zWxey!_9%hxwH2_dEJi=yY|1c7nDm2_Lm!Cof8-R_+9UkS zcBE(o47yE)oMR(Q=dp1a2wTX5KvvGyLqlWTa7V&!A*|w|)ax~1_~aJ0=_Lilg*0iQk7#ZD EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/styles.css b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/styles.css new file mode 100644 index 0000000..141f7f9 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/styles.css @@ -0,0 +1,56 @@ +.list-view-loading +{ + background:url(loading.gif) no-repeat; +} + +.list-view .summary +{ + margin: 0 0 5px 0; + text-align: right; +} + +.list-view .sorter +{ + margin: 0 0 5px 0; + text-align: right; +} + +.list-view .pager +{ + margin: 5px 0 0 0; + text-align: right; +} + +.list-view .sorter +{ + font-size: 0.9em; +} + +.list-view .sorter ul +{ + display: inline; + list-style-image:none; + list-style-position:outside; + list-style-type:none; + margin:0; + padding:0; +} + +.list-view .sorter li +{ + display: inline; + margin: 0 0 0 5px; + padding: 0; +} + +.list-view .sorter a.asc +{ + background:url(up.gif) right center no-repeat; + padding-right: 10px; +} + +.list-view .sorter a.desc +{ + background:url(down.gif) right center no-repeat; + padding-right: 10px; +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/up.gif b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/assets/listview/up.gif new file mode 100644 index 0000000000000000000000000000000000000000..890b03882768a83dcee5a2b0afbc69767d3c4eb3 GIT binary patch literal 54 ycmZ?wbhEHbWM^Pun8*ME|G@yrQ2fcl$iTqFpaT*G$ulsqPf6rleVUJ(!5RR0;|yp3 literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CButtonColumn.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CButtonColumn.php new file mode 100644 index 0000000..d7565f4 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CButtonColumn.php @@ -0,0 +1,349 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.grid.CGridColumn'); + +/** + * CButtonColumn represents a grid view column that renders one or several buttons. + * + * By default, it will display three buttons, "view", "update" and "delete", which triggers the corresponding + * actions on the model of the row. + * + * By configuring {@link buttons} and {@link template} properties, the column can display other buttons + * and customize the display order of the buttons. + * + * @author Qiang Xue + * @package zii.widgets.grid + * @since 1.1 + */ +class CButtonColumn extends CGridColumn +{ + /** + * @var array the HTML options for the data cell tags. + */ + public $htmlOptions=array('class'=>'button-column'); + /** + * @var array the HTML options for the header cell tag. + */ + public $headerHtmlOptions=array('class'=>'button-column'); + /** + * @var array the HTML options for the footer cell tag. + */ + public $footerHtmlOptions=array('class'=>'button-column'); + /** + * @var string the template that is used to render the content in each data cell. + * These default tokens are recognized: {view}, {update} and {delete}. If the {@link buttons} property + * defines additional buttons, their IDs are also recognized here. For example, if a button named 'preview' + * is declared in {@link buttons}, we can use the token '{preview}' here to specify where to display the button. + */ + public $template='{view} {update} {delete}'; + /** + * @var string the label for the view button. Defaults to "View". + * Note that the label will not be HTML-encoded when rendering. + */ + public $viewButtonLabel; + /** + * @var string the image URL for the view button. If not set, an integrated image will be used. + * You may set this property to be false to render a text link instead. + */ + public $viewButtonImageUrl; + /** + * @var string a PHP expression that is evaluated for every view button and whose result is used + * as the URL for the view button. In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the column object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + */ + public $viewButtonUrl='Yii::app()->controller->createUrl("view",array("id"=>$data->primaryKey))'; + /** + * @var array the HTML options for the view button tag. + */ + public $viewButtonOptions=array('class'=>'view'); + + /** + * @var string the label for the update button. Defaults to "Update". + * Note that the label will not be HTML-encoded when rendering. + */ + public $updateButtonLabel; + /** + * @var string the image URL for the update button. If not set, an integrated image will be used. + * You may set this property to be false to render a text link instead. + */ + public $updateButtonImageUrl; + /** + * @var string a PHP expression that is evaluated for every update button and whose result is used + * as the URL for the update button. In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the column object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + */ + public $updateButtonUrl='Yii::app()->controller->createUrl("update",array("id"=>$data->primaryKey))'; + /** + * @var array the HTML options for the update button tag. + */ + public $updateButtonOptions=array('class'=>'update'); + + /** + * @var string the label for the delete button. Defaults to "Delete". + * Note that the label will not be HTML-encoded when rendering. + */ + public $deleteButtonLabel; + /** + * @var string the image URL for the delete button. If not set, an integrated image will be used. + * You may set this property to be false to render a text link instead. + */ + public $deleteButtonImageUrl; + /** + * @var string a PHP expression that is evaluated for every delete button and whose result is used + * as the URL for the delete button. In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the column object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + */ + public $deleteButtonUrl='Yii::app()->controller->createUrl("delete",array("id"=>$data->primaryKey))'; + /** + * @var array the HTML options for the delete button tag. + */ + public $deleteButtonOptions=array('class'=>'delete'); + /** + * @var string the confirmation message to be displayed when delete button is clicked. + * By setting this property to be false, no confirmation message will be displayed. + * This property is used only if $this->buttons['delete']['click'] is not set. + */ + public $deleteConfirmation; + /** + * @var string a javascript function that will be invoked after the delete ajax call. + * This property is used only if $this->buttons['delete']['click'] is not set. + * + * The function signature is function(link, success, data) + *
                + *
              • link references the delete link.
              • + *
              • success status of the ajax call, true if the ajax call was successful, false if the ajax call failed. + *
              • data the data returned by the server in case of a successful call or XHR object in case of error. + *
              + * Note that if success is true it does not mean that the delete was successful, it only means that the ajax call was successful. + * + * Example: + *
              +	 *  array(
              +	 *     class'=>'CButtonColumn',
              +	 *     'afterDelete'=>'function(link,success,data){ if(success) alert("Delete completed successfuly"); }',
              +	 *  ),
              +	 * 
              + */ + public $afterDelete; + /** + * @var array the configuration for buttons. Each array element specifies a single button + * which has the following format: + *
              +	 * 'buttonID' => array(
              +	 *     'label'=>'...',     // text label of the button
              +	 *     'url'=>'...',       // a PHP expression for generating the URL of the button
              +	 *     'imageUrl'=>'...',  // image URL of the button. If not set or false, a text link is used
              +	 *     'options'=>array(...), // HTML options for the button tag
              +	 *     'click'=>'...',     // a JS function to be invoked when the button is clicked
              +	 *     'visible'=>'...',   // a PHP expression for determining whether the button is visible
              +	 * )
              +	 * 
              + * + * In the PHP expression for the 'url' option and/or 'visible' option, the variable $row + * refers to the current row number (zero-based), and $data refers to the data model for + * the row. + * The PHP expression will be evaluated using {@link evaluateExpression}. + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + * + * If the 'buttonID' is 'view', 'update' or 'delete' the options will be applied to the default buttons. + * + * Note that in order to display non-default buttons, the {@link template} property needs to + * be configured so that the corresponding button IDs appear as tokens in the template. + */ + public $buttons=array(); + + /** + * Initializes the column. + * This method registers necessary client script for the button column. + */ + public function init() + { + $this->initDefaultButtons(); + + foreach($this->buttons as $id=>$button) + { + if(strpos($this->template,'{'.$id.'}')===false) + unset($this->buttons[$id]); + elseif(isset($button['click'])) + { + if(!isset($button['options']['class'])) + $this->buttons[$id]['options']['class']=$id; + if(!($button['click'] instanceof CJavaScriptExpression)) + $this->buttons[$id]['click']=new CJavaScriptExpression($button['click']); + } + } + + $this->registerClientScript(); + } + + /** + * Initializes the default buttons (view, update and delete). + */ + protected function initDefaultButtons() + { + if($this->viewButtonLabel===null) + $this->viewButtonLabel=Yii::t('zii','View'); + if($this->updateButtonLabel===null) + $this->updateButtonLabel=Yii::t('zii','Update'); + if($this->deleteButtonLabel===null) + $this->deleteButtonLabel=Yii::t('zii','Delete'); + if($this->viewButtonImageUrl===null) + $this->viewButtonImageUrl=$this->grid->baseScriptUrl.'/view.png'; + if($this->updateButtonImageUrl===null) + $this->updateButtonImageUrl=$this->grid->baseScriptUrl.'/update.png'; + if($this->deleteButtonImageUrl===null) + $this->deleteButtonImageUrl=$this->grid->baseScriptUrl.'/delete.png'; + if($this->deleteConfirmation===null) + $this->deleteConfirmation=Yii::t('zii','Are you sure you want to delete this item?'); + + foreach(array('view','update','delete') as $id) + { + $button=array( + 'label'=>$this->{$id.'ButtonLabel'}, + 'url'=>$this->{$id.'ButtonUrl'}, + 'imageUrl'=>$this->{$id.'ButtonImageUrl'}, + 'options'=>$this->{$id.'ButtonOptions'}, + ); + if(isset($this->buttons[$id])) + $this->buttons[$id]=array_merge($button,$this->buttons[$id]); + else + $this->buttons[$id]=$button; + } + + if(!isset($this->buttons['delete']['click'])) + { + if(is_string($this->deleteConfirmation)) + $confirmation="if(!confirm(".CJavaScript::encode($this->deleteConfirmation).")) return false;"; + else + $confirmation=''; + + if(Yii::app()->request->enableCsrfValidation) + { + $csrfTokenName = Yii::app()->request->csrfTokenName; + $csrfToken = Yii::app()->request->csrfToken; + $csrf = "\n\t\tdata:{ '$csrfTokenName':'$csrfToken' },"; + } + else + $csrf = ''; + + if($this->afterDelete===null) + $this->afterDelete='function(){}'; + + $this->buttons['delete']['click']=<<afterDelete; + jQuery('#{$this->grid->id}').yiiGridView('update', { + type: 'POST', + url: jQuery(this).attr('href'),$csrf + success: function(data) { + jQuery('#{$this->grid->id}').yiiGridView('update'); + afterDelete(th, true, data); + }, + error: function(XHR) { + return afterDelete(th, false, XHR); + } + }); + return false; +} +EOD; + } + } + + /** + * Registers the client scripts for the button column. + */ + protected function registerClientScript() + { + $js=array(); + foreach($this->buttons as $id=>$button) + { + if(isset($button['click'])) + { + $function=CJavaScript::encode($button['click']); + $class=preg_replace('/\s+/','.',$button['options']['class']); + $js[]="jQuery(document).on('click','#{$this->grid->id} a.{$class}',$function);"; + } + } + + if($js!==array()) + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$this->id, implode("\n",$js)); + } + + /** + * Renders the data cell content. + * This method renders the view, update and delete buttons in the data cell. + * @param integer $row the row number (zero-based) + * @param mixed $data the data associated with the row + */ + protected function renderDataCellContent($row,$data) + { + $tr=array(); + ob_start(); + foreach($this->buttons as $id=>$button) + { + $this->renderButton($id,$button,$row,$data); + $tr['{'.$id.'}']=ob_get_contents(); + ob_clean(); + } + ob_end_clean(); + echo strtr($this->template,$tr); + } + + /** + * Renders a link button. + * @param string $id the ID of the button + * @param array $button the button configuration which may contain 'label', 'url', 'imageUrl' and 'options' elements. + * See {@link buttons} for more details. + * @param integer $row the row number (zero-based) + * @param mixed $data the data object associated with the row + */ + protected function renderButton($id,$button,$row,$data) + { + if (isset($button['visible']) && !$this->evaluateExpression($button['visible'],array('row'=>$row,'data'=>$data))) + return; + $label=isset($button['label']) ? $button['label'] : $id; + $url=isset($button['url']) ? $this->evaluateExpression($button['url'],array('data'=>$data,'row'=>$row)) : '#'; + $options=isset($button['options']) ? $button['options'] : array(); + if(!isset($options['title'])) + $options['title']=$label; + if(isset($button['imageUrl']) && is_string($button['imageUrl'])) + echo CHtml::link(CHtml::image($button['imageUrl'],$label),$url,$options); + else + echo CHtml::link($label,$url,$options); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CCheckBoxColumn.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CCheckBoxColumn.php new file mode 100644 index 0000000..e6ffcc2 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CCheckBoxColumn.php @@ -0,0 +1,248 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.grid.CGridColumn'); + +/** + * CCheckBoxColumn represents a grid view column of checkboxes. + * + * CCheckBoxColumn supports no checking (read-only), single check and multiple checking. + * The mode is determined according to {@link selectableRows}. When in multiple checking mode, the header cell will display + * an additional checkbox, clicking on which will check or uncheck all of the checkboxes in the data cells. + * The header cell can be customized by {@link headerTemplate}. + * + * Additionally selecting a checkbox can select a grid view row (depending on {@link CGridView::selectableRows} value) if + * {@link selectableRows} is null (default). + * + * By default, the checkboxes rendered in data cells will have the values that are the same as + * the key values of the data model. One may change this by setting either {@link name} or + * {@link value}. + * + * @author Qiang Xue + * @package zii.widgets.grid + * @since 1.1 + */ +class CCheckBoxColumn extends CGridColumn +{ + /** + * @var string the attribute name of the data model. The corresponding attribute value will be rendered + * in each data cell as the checkbox value. Note that if {@link value} is specified, this property will be ignored. + * @see value + */ + public $name; + /** + * @var string a PHP expression that will be evaluated for every data cell and whose result will be rendered + * in each data cell as the checkbox value. In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the column object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + */ + public $value; + /** + * @var string a PHP expression that will be evaluated for every data cell and whose result will + * determine if checkbox for each data cell is checked. In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the column object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + * @since 1.1.4 + */ + public $checked; + /** + * @var string a PHP expression that will be evaluated for every data cell and whose result will + * determine if checkbox for each data cell is disabled. In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the column object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + * + * Note that expression result will overwrite value set with checkBoxHtmlOptions['disabled']. + * @since 1.1.13 + */ + public $disabled; + /** + * @var array the HTML options for the data cell tags. + */ + public $htmlOptions=array('class'=>'checkbox-column'); + /** + * @var array the HTML options for the header cell tag. + */ + public $headerHtmlOptions=array('class'=>'checkbox-column'); + /** + * @var array the HTML options for the footer cell tag. + */ + public $footerHtmlOptions=array('class'=>'checkbox-column'); + /** + * @var array the HTML options for the checkboxes. + */ + public $checkBoxHtmlOptions=array(); + /** + * @var integer the number of rows that can be checked. + * Possible values: + *
                + *
              • 0 - the state of the checkbox cannot be changed (read-only mode)
              • + *
              • 1 - only one row can be checked. Checking a checkbox has nothing to do with selecting the row
              • + *
              • 2 or more - multiple checkboxes can be checked. Checking a checkbox has nothing to do with selecting the row
              • + *
              • null - {@link CGridView::selectableRows} is used to control how many checkboxes can be checked. + * Checking a checkbox will also select the row.
              • + *
              + * You may also call the JavaScript function $(gridID).yiiGridView('getChecked', columnID) + * to retrieve the key values of the checked rows. + * @since 1.1.6 + */ + public $selectableRows=null; + /** + * @var string the template to be used to control the layout of the header cell. + * The token "{item}" is recognized and it will be replaced with a "check all" checkbox. + * By default if in multiple checking mode, the header cell will display an additional checkbox, + * clicking on which will check or uncheck all of the checkboxes in the data cells. + * See {@link selectableRows} for more details. + * @since 1.1.11 + */ + public $headerTemplate='{item}'; + + /** + * Initializes the column. + * This method registers necessary client script for the checkbox column. + */ + public function init() + { + if(isset($this->checkBoxHtmlOptions['name'])) + $name=$this->checkBoxHtmlOptions['name']; + else + { + $name=$this->id; + if(substr($name,-2)!=='[]') + $name.='[]'; + $this->checkBoxHtmlOptions['name']=$name; + } + $name=strtr($name,array('['=>"\\[",']'=>"\\]")); + + if($this->selectableRows===null) + { + if(isset($this->checkBoxHtmlOptions['class'])) + $this->checkBoxHtmlOptions['class'].=' select-on-check'; + else + $this->checkBoxHtmlOptions['class']='select-on-check'; + return; + } + + $cball=$cbcode=''; + if($this->selectableRows==0) + { + //.. read only + $cbcode="return false;"; + } + elseif($this->selectableRows==1) + { + //.. only one can be checked, uncheck all other + $cbcode="jQuery(\"input:not(#\"+this.id+\")[name='$name']\").prop('checked',false);"; + } + elseif(strpos($this->headerTemplate,'{item}')!==false) + { + //.. process check/uncheck all + $cball=<<id}_all',function() { + var checked=this.checked; + jQuery("input[name='$name']:enabled").each(function() {this.checked=checked;}); +}); + +CBALL; + $cbcode="jQuery('#{$this->id}_all').prop('checked', jQuery(\"input[name='$name']\").length==jQuery(\"input[name='$name']:checked\").length);"; + } + + if($cbcode!=='') + { + $js=$cball; + $js.=<<getClientScript()->registerScript(__CLASS__.'#'.$this->id,$js); + } + } + + /** + * Renders the header cell content. + * This method will render a checkbox in the header when {@link selectableRows} is greater than 1 + * or in case {@link selectableRows} is null when {@link CGridView::selectableRows} is greater than 1. + */ + protected function renderHeaderCellContent() + { + if(trim($this->headerTemplate)==='') + { + echo $this->grid->blankDisplay; + return; + } + + $item = ''; + if($this->selectableRows===null && $this->grid->selectableRows>1) + $item = CHtml::checkBox($this->id.'_all',false,array('class'=>'select-on-check-all')); + elseif($this->selectableRows>1) + $item = CHtml::checkBox($this->id.'_all',false); + else + { + ob_start(); + parent::renderHeaderCellContent(); + $item = ob_get_clean(); + } + + echo strtr($this->headerTemplate,array( + '{item}'=>$item, + )); + } + + /** + * Renders the data cell content. + * This method renders a checkbox in the data cell. + * @param integer $row the row number (zero-based) + * @param mixed $data the data associated with the row + */ + protected function renderDataCellContent($row,$data) + { + if($this->value!==null) + $value=$this->evaluateExpression($this->value,array('data'=>$data,'row'=>$row)); + elseif($this->name!==null) + $value=CHtml::value($data,$this->name); + else + $value=$this->grid->dataProvider->keys[$row]; + + $checked = false; + if($this->checked!==null) + $checked=$this->evaluateExpression($this->checked,array('data'=>$data,'row'=>$row)); + + $options=$this->checkBoxHtmlOptions; + if($this->disabled!==null) + $options['disabled']=$this->evaluateExpression($this->disabled,array('data'=>$data,'row'=>$row)); + + $name=$options['name']; + unset($options['name']); + $options['value']=$value; + $options['id']=$this->id.'_'.$row; + echo CHtml::checkBox($name,$checked,$options); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CDataColumn.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CDataColumn.php new file mode 100644 index 0000000..4940821 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CDataColumn.php @@ -0,0 +1,142 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.grid.CGridColumn'); + +/** + * CDataColumn represents a grid view column that is associated with a data attribute or PHP expression. + * + * Either {@link name} or {@link value} should be specified. The former specifies + * a data attribute name, while the latter a PHP expression whose value should be rendered instead. + * + * The property {@link sortable} determines whether the grid view can be sorted according to this column. + * Note that the {@link name} should always be set if the column needs to be sortable. The {@link name} + * value will be used by {@link CSort} to render a clickable link in the header cell to trigger the sorting. + * + * @author Qiang Xue + * @package zii.widgets.grid + * @since 1.1 + */ +class CDataColumn extends CGridColumn +{ + /** + * @var string the attribute name of the data model. Used for column sorting, filtering and to render the corresponding + * attribute value in each data cell. If {@link value} is specified it will be used to rendered the data cell instead of the attribute value. + * @see value + * @see sortable + */ + public $name; + /** + * @var string a PHP expression that will be evaluated for every data cell using {@link evaluateExpression} and whose result will be rendered + * as the content of the data cell. + * In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based).
              • + *
              • $data the data model for the row.
              • + *
              • $this the column object.
              • + *
              + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + */ + public $value; + /** + * @var string the type of the attribute value. This determines how the attribute value is formatted for display. + * Valid values include those recognizable by {@link CGridView::formatter}, such as: raw, text, ntext, html, date, time, + * datetime, boolean, number, email, image, url. For more details, please refer to {@link CFormatter}. + * Defaults to 'text' which means the attribute value will be HTML-encoded. + */ + public $type='text'; + /** + * @var boolean whether the column is sortable. If so, the header cell will contain a link that may trigger the sorting. + * Defaults to true. Note that if {@link name} is not set, or if {@link name} is not allowed by {@link CSort}, + * this property will be treated as false. + * @see name + */ + public $sortable=true; + /** + * @var mixed the HTML code representing a filter input (eg a text field, a dropdown list) + * that is used for this data column. This property is effective only when + * {@link CGridView::filter} is set. + * If this property is not set, a text field will be generated as the filter input; + * If this property is an array, a dropdown list will be generated that uses this property value as + * the list options. + * If you don't want a filter for this data column, set this value to false. + * @since 1.1.1 + */ + public $filter; + + /** + * Initializes the column. + */ + public function init() + { + parent::init(); + if($this->name===null) + $this->sortable=false; + if($this->name===null && $this->value===null) + throw new CException(Yii::t('zii','Either "name" or "value" must be specified for CDataColumn.')); + } + + /** + * Renders the filter cell content. + * This method will render the {@link filter} as is if it is a string. + * If {@link filter} is an array, it is assumed to be a list of options, and a dropdown selector will be rendered. + * Otherwise if {@link filter} is not false, a text field is rendered. + * @since 1.1.1 + */ + protected function renderFilterCellContent() + { + if(is_string($this->filter)) + echo $this->filter; + elseif($this->filter!==false && $this->grid->filter!==null && $this->name!==null && strpos($this->name,'.')===false) + { + if(is_array($this->filter)) + echo CHtml::activeDropDownList($this->grid->filter, $this->name, $this->filter, array('id'=>false,'prompt'=>'')); + elseif($this->filter===null) + echo CHtml::activeTextField($this->grid->filter, $this->name, array('id'=>false)); + } + else + parent::renderFilterCellContent(); + } + + /** + * Renders the header cell content. + * This method will render a link that can trigger the sorting if the column is sortable. + */ + protected function renderHeaderCellContent() + { + if($this->grid->enableSorting && $this->sortable && $this->name!==null) + echo $this->grid->dataProvider->getSort()->link($this->name,$this->header,array('class'=>'sort-link')); + elseif($this->name!==null && $this->header===null) + { + if($this->grid->dataProvider instanceof CActiveDataProvider) + echo CHtml::encode($this->grid->dataProvider->model->getAttributeLabel($this->name)); + else + echo CHtml::encode($this->name); + } + else + parent::renderHeaderCellContent(); + } + + /** + * Renders the data cell content. + * This method evaluates {@link value} or {@link name} and renders the result. + * @param integer $row the row number (zero-based) + * @param mixed $data the data associated with the row + */ + protected function renderDataCellContent($row,$data) + { + if($this->value!==null) + $value=$this->evaluateExpression($this->value,array('data'=>$data,'row'=>$row)); + elseif($this->name!==null) + $value=CHtml::value($data,$this->name); + echo $value===null ? $this->grid->nullDisplay : $this->grid->getFormatter()->format($value,$this->type); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CGridColumn.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CGridColumn.php new file mode 100644 index 0000000..a90d4cb --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CGridColumn.php @@ -0,0 +1,206 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CGridColumn is the base class for all grid view column classes. + * + * A CGridColumn object represents the specification for rendering the cells in + * a particular grid view column. + * + * In a column, there is one header cell, multiple data cells, and an optional footer cell. + * Child classes may override {@link renderHeaderCellContent}, {@link renderDataCellContent} + * and {@link renderFooterCellContent} to customize how these cells are rendered. + * + * @property boolean $hasFooter Whether this column has a footer cell. + * This is determined based on whether {@link footer} is set. + * + * @author Qiang Xue + * @package zii.widgets.grid + * @since 1.1 + */ +abstract class CGridColumn extends CComponent +{ + /** + * @var string the ID of this column. This value should be unique among all grid view columns. + * If this is not set, it will be assigned one automatically. + */ + public $id; + /** + * @var CGridView the grid view object that owns this column. + */ + public $grid; + /** + * @var string the header cell text. Note that it will not be HTML-encoded. + */ + public $header; + /** + * @var string the footer cell text. Note that it will not be HTML-encoded. + */ + public $footer; + /** + * @var boolean whether this column is visible. Defaults to true. + */ + public $visible=true; + /** + * @var string a PHP expression that is evaluated for every data cell and whose result + * is used as the CSS class name for the data cell. In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the column object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + */ + public $cssClassExpression; + /** + * @var array the HTML options for the data cell tags. + */ + public $htmlOptions=array(); + /** + * @var array the HTML options for the filter cell tag. + */ + public $filterHtmlOptions=array(); + /** + * @var array the HTML options for the header cell tag. + */ + public $headerHtmlOptions=array(); + /** + * @var array the HTML options for the footer cell tag. + */ + public $footerHtmlOptions=array(); + + /** + * Constructor. + * @param CGridView $grid the grid view that owns this column. + */ + public function __construct($grid) + { + $this->grid=$grid; + } + + /** + * Initializes the column. + * This method is invoked by the grid view when it initializes itself before rendering. + * You may override this method to prepare the column for rendering. + */ + public function init() + { + } + + /** + * @return boolean whether this column has a footer cell. + * This is determined based on whether {@link footer} is set. + */ + public function getHasFooter() + { + return $this->footer!==null; + } + + /** + * Renders the filter cell. + * @since 1.1.1 + */ + public function renderFilterCell() + { + echo CHtml::openTag('td',$this->filterHtmlOptions); + $this->renderFilterCellContent(); + echo ""; + } + + /** + * Renders the header cell. + */ + public function renderHeaderCell() + { + $this->headerHtmlOptions['id']=$this->id; + echo CHtml::openTag('th',$this->headerHtmlOptions); + $this->renderHeaderCellContent(); + echo ""; + } + + /** + * Renders a data cell. + * @param integer $row the row number (zero-based) + */ + public function renderDataCell($row) + { + $data=$this->grid->dataProvider->data[$row]; + $options=$this->htmlOptions; + if($this->cssClassExpression!==null) + { + $class=$this->evaluateExpression($this->cssClassExpression,array('row'=>$row,'data'=>$data)); + if(!empty($class)) + { + if(isset($options['class'])) + $options['class'].=' '.$class; + else + $options['class']=$class; + } + } + echo CHtml::openTag('td',$options); + $this->renderDataCellContent($row,$data); + echo ''; + } + + /** + * Renders the footer cell. + */ + public function renderFooterCell() + { + echo CHtml::openTag('td',$this->footerHtmlOptions); + $this->renderFooterCellContent(); + echo ''; + } + + /** + * Renders the header cell content. + * The default implementation simply renders {@link header}. + * This method may be overridden to customize the rendering of the header cell. + */ + protected function renderHeaderCellContent() + { + echo trim($this->header)!=='' ? $this->header : $this->grid->blankDisplay; + } + + /** + * Renders the footer cell content. + * The default implementation simply renders {@link footer}. + * This method may be overridden to customize the rendering of the footer cell. + */ + protected function renderFooterCellContent() + { + echo trim($this->footer)!=='' ? $this->footer : $this->grid->blankDisplay; + } + + /** + * Renders the data cell content. + * This method SHOULD be overridden to customize the rendering of the data cell. + * @param integer $row the row number (zero-based) + * @param mixed $data the data associated with the row + */ + protected function renderDataCellContent($row,$data) + { + echo $this->grid->blankDisplay; + } + + /** + * Renders the filter cell content. + * The default implementation simply renders a space. + * This method may be overridden to customize the rendering of the filter cell (if any). + * @since 1.1.1 + */ + protected function renderFilterCellContent() + { + echo $this->grid->blankDisplay; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CGridView.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CGridView.php new file mode 100644 index 0000000..cb078f5 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CGridView.php @@ -0,0 +1,649 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.CBaseListView'); +Yii::import('zii.widgets.grid.CDataColumn'); +Yii::import('zii.widgets.grid.CLinkColumn'); +Yii::import('zii.widgets.grid.CButtonColumn'); +Yii::import('zii.widgets.grid.CCheckBoxColumn'); + +/** + * CGridView displays a list of data items in terms of a table. + * + * Each row of the table represents the data of a single data item, and a column usually represents + * an attribute of the item (some columns may correspond to complex expression of attributes or static text). + * + * CGridView supports both sorting and pagination of the data items. The sorting + * and pagination can be done in AJAX mode or normal page request. A benefit of using CGridView is that + * when the user browser disables JavaScript, the sorting and pagination automatically degenerate + * to normal page requests and are still functioning as expected. + * + * CGridView should be used together with a {@link IDataProvider data provider}, preferrably a + * {@link CActiveDataProvider}. + * + * The minimal code needed to use CGridView is as follows: + * + *
              + * $dataProvider=new CActiveDataProvider('Post');
              + *
              + * $this->widget('zii.widgets.grid.CGridView', array(
              + *     'dataProvider'=>$dataProvider,
              + * ));
              + * 
              + * + * The above code first creates a data provider for the Post ActiveRecord class. + * It then uses CGridView to display every attribute in every Post instance. + * The displayed table is equiped with sorting and pagination functionality. + * + * In order to selectively display attributes with different formats, we may configure the + * {@link CGridView::columns} property. For example, we may specify only the title + * and create_time attributes to be displayed, and the create_time + * should be properly formatted to show as a time. We may also display the attributes of the related + * objects using the dot-syntax as shown below: + * + *
              + * $this->widget('zii.widgets.grid.CGridView', array(
              + *     'dataProvider'=>$dataProvider,
              + *     'columns'=>array(
              + *         'title',          // display the 'title' attribute
              + *         'category.name',  // display the 'name' attribute of the 'category' relation
              + *         'content:html',   // display the 'content' attribute as purified HTML
              + *         array(            // display 'create_time' using an expression
              + *             'name'=>'create_time',
              + *             'value'=>'date("M j, Y", $data->create_time)',
              + *         ),
              + *         array(            // display 'author.username' using an expression
              + *             'name'=>'authorName',
              + *             'value'=>'$data->author->username',
              + *         ),
              + *         array(            // display a column with "view", "update" and "delete" buttons
              + *             'class'=>'CButtonColumn',
              + *         ),
              + *     ),
              + * ));
              + * 
              + * + * Please refer to {@link columns} for more details about how to configure this property. + * + * @property boolean $hasFooter Whether the table should render a footer. + * This is true if any of the {@link columns} has a true {@link CGridColumn::hasFooter} value. + * @property CFormatter $formatter The formatter instance. Defaults to the 'format' application component. + * + * @author Qiang Xue + * @package zii.widgets.grid + * @since 1.1 + */ +class CGridView extends CBaseListView +{ + const FILTER_POS_HEADER='header'; + const FILTER_POS_FOOTER='footer'; + const FILTER_POS_BODY='body'; + + private $_formatter; + /** + * @var array grid column configuration. Each array element represents the configuration + * for one particular grid column which can be either a string or an array. + * + * When a column is specified as a string, it should be in the format of "name:type:header", + * where "type" and "header" are optional. A {@link CDataColumn} instance will be created in this case, + * whose {@link CDataColumn::name}, {@link CDataColumn::type} and {@link CDataColumn::header} + * properties will be initialized accordingly. + * + * When a column is specified as an array, it will be used to create a grid column instance, where + * the 'class' element specifies the column class name (defaults to {@link CDataColumn} if absent). + * Currently, these official column classes are provided: {@link CDataColumn}, + * {@link CLinkColumn}, {@link CButtonColumn} and {@link CCheckBoxColumn}. + */ + public $columns=array(); + /** + * @var array the CSS class names for the table body rows. If multiple CSS class names are given, + * they will be assigned to the rows sequentially and repeatedly. This property is ignored + * if {@link rowCssClassExpression} is set. Defaults to array('odd', 'even'). + * @see rowCssClassExpression + */ + public $rowCssClass=array('odd','even'); + /** + * @var string a PHP expression that is evaluated for every table body row and whose result + * is used as the CSS class name for the row. In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the grid view object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + * @see rowCssClass + * @deprecated in 1.1.13 in favor of {@link rowHtmlOptionsExpression} + */ + public $rowCssClassExpression; + /** + * @var string a PHP expression that is evaluated for every table body row and whose result + * is used as additional HTML attributes for the row. The expression should return an + * array whose key value pairs correspond to html attribute and value. + * In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based)
              • + *
              • $data the data model for the row
              • + *
              • $this the grid view object
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + * @since 1.1.13 + */ + public $rowHtmlOptionsExpression; + /** + * @var boolean whether to display the table even when there is no data. Defaults to true. + * The {@link emptyText} will be displayed to indicate there is no data. + */ + public $showTableOnEmpty=true; + /** + * @var mixed the ID of the container whose content may be updated with an AJAX response. + * Defaults to null, meaning the container for this grid view instance. + * If it is set false, it means sorting and pagination will be performed in normal page requests + * instead of AJAX requests. If the sorting and pagination should trigger the update of multiple + * containers' content in AJAX fashion, these container IDs may be listed here (separated with comma). + */ + public $ajaxUpdate; + /** + * @var string the jQuery selector of the HTML elements that may trigger AJAX updates when they are clicked. + * These tokens are recognized: {page} and {sort}. They will be replaced with the pagination and sorting links selectors. + * Defaults to '{page}, {sort}', that means that the pagination links and the sorting links will trigger AJAX updates. + * Tokens are available from 1.1.11 + * + * Note: if this value is empty an exception will be thrown. + * + * Example (adding a custom selector to the default ones): + *
              +	 *  ...
              +	 *  'updateSelector'=>'{page}, {sort}, #mybutton',
              +	 *  ...
              +	 * 
              + * @since 1.1.7 + */ + public $updateSelector='{page}, {sort}'; + /** + * @var string a javascript function that will be invoked if an AJAX update error occurs. + * + * The function signature is function(xhr, textStatus, errorThrown, errorMessage) + *
                + *
              • xhr is the XMLHttpRequest object.
              • + *
              • textStatus is a string describing the type of error that occurred. + * Possible values (besides null) are "timeout", "error", "notmodified" and "parsererror"
              • + *
              • errorThrown is an optional exception object, if one occurred.
              • + *
              • errorMessage is the CGridView default error message derived from xhr and errorThrown. + * Usefull if you just want to display this error differently. CGridView by default displays this error with an javascript.alert()
              • + *
              + * Note: This handler is not called for JSONP requests, because they do not use an XMLHttpRequest. + * + * Example (add in a call to CGridView): + *
              +	 *  ...
              +	 *  'ajaxUpdateError'=>'function(xhr,ts,et,err){ $("#myerrordiv").text(err); }',
              +	 *  ...
              +	 * 
              + */ + public $ajaxUpdateError; + /** + * @var string the name of the GET variable that indicates the request is an AJAX request triggered + * by this widget. Defaults to 'ajax'. This is effective only when {@link ajaxUpdate} is not false. + */ + public $ajaxVar='ajax'; + /** + * @var mixed the URL for the AJAX requests should be sent to. {@link CHtml::normalizeUrl()} will be + * called on this property. If not set, the current page URL will be used for AJAX requests. + * @since 1.1.8 + */ + public $ajaxUrl; + /** + * @var string the type ('GET' or 'POST') of the AJAX requests. If not set, 'GET' will be used. + * You can set this to 'POST' if you are filtering by many fields at once and have a problem with GET query string length. + * Note that in POST mode direct links and {@link enableHistory} feature may not work correctly! + * @since 1.1.14 + */ + public $ajaxType; + /** + * @var string a javascript function that will be invoked before an AJAX update occurs. + * The function signature is function(id,options) where 'id' refers to the ID of the grid view, + * 'options' the AJAX request options (see jQuery.ajax api manual). + */ + public $beforeAjaxUpdate; + /** + * @var string a javascript function that will be invoked after a successful AJAX response is received. + * The function signature is function(id, data) where 'id' refers to the ID of the grid view, + * 'data' the received ajax response data. + */ + public $afterAjaxUpdate; + /** + * @var string a javascript function that will be invoked after the row selection is changed. + * The function signature is function(id) where 'id' refers to the ID of the grid view. + * In this function, you may use $(gridID).yiiGridView('getSelection') to get the key values + * of the currently selected rows (gridID is the DOM selector of the grid). + * @see selectableRows + */ + public $selectionChanged; + /** + * @var integer the number of table body rows that can be selected. If 0, it means rows cannot be selected. + * If 1, only one row can be selected. If 2 or any other number, it means multiple rows can be selected. + * A selected row will have a CSS class named 'selected'. You may also call the JavaScript function + * $(gridID).yiiGridView('getSelection') to retrieve the key values of the currently selected + * rows (gridID is the DOM selector of the grid). + */ + public $selectableRows=1; + /** + * @var string the base script URL for all grid view resources (eg javascript, CSS file, images). + * Defaults to null, meaning using the integrated grid view resources (which are published as assets). + */ + public $baseScriptUrl; + /** + * @var string the URL of the CSS file used by this grid view. Defaults to null, meaning using the integrated + * CSS file. If this is set false, you are responsible to explicitly include the necessary CSS file in your page. + */ + public $cssFile; + /** + * @var string the text to be displayed in a data cell when a data value is null. This property will NOT be HTML-encoded + * when rendering. Defaults to an HTML blank. + */ + public $nullDisplay=' '; + /** + * @var string the text to be displayed in an empty grid cell. This property will NOT be HTML-encoded when rendering. Defaults to an HTML blank. + * This differs from {@link nullDisplay} in that {@link nullDisplay} is only used by {@link CDataColumn} to render + * null data values. + * @since 1.1.7 + */ + public $blankDisplay=' '; + /** + * @var string the CSS class name that will be assigned to the widget container element + * when the widget is updating its content via AJAX. Defaults to 'grid-view-loading'. + * @since 1.1.1 + */ + public $loadingCssClass='grid-view-loading'; + /** + * @var string the jQuery selector of filter input fields. + * The token '{filter}' is recognized and it will be replaced with the grid filters selector. + * Defaults to '{filter}'. + * + * Note: if this value is empty an exception will be thrown. + * + * Example (adding a custom selector to the default one): + *
              +	 *  ...
              +	 *  'filterSelector'=>'{filter}, #myfilter',
              +	 *  ...
              +	 * 
              + * @since 1.1.13 + */ + public $filterSelector='{filter}'; + /** + * @var string the CSS class name for the table row element containing all filter input fields. Defaults to 'filters'. + * @see filter + * @since 1.1.1 + */ + public $filterCssClass='filters'; + /** + * @var string whether the filters should be displayed in the grid view. Valid values include: + *
                + *
              • header: the filters will be displayed on top of each column's header cell.
              • + *
              • body: the filters will be displayed right below each column's header cell.
              • + *
              • footer: the filters will be displayed below each column's footer cell.
              • + *
              + * @see filter + * @since 1.1.1 + */ + public $filterPosition='body'; + /** + * @var CModel the model instance that keeps the user-entered filter data. When this property is set, + * the grid view will enable column-based filtering. Each data column by default will display a text field + * at the top that users can fill in to filter the data. + * Note that in order to show an input field for filtering, a column must have its {@link CDataColumn::name} + * property set or have {@link CDataColumn::filter} as the HTML code for the input field. + * When this property is not set (null) the filtering is disabled. + * @since 1.1.1 + */ + public $filter; + /** + * @var boolean whether to hide the header cells of the grid. When this is true, header cells + * will not be rendered, which means the grid cannot be sorted anymore since the sort links are located + * in the header. Defaults to false. + * @since 1.1.1 + */ + public $hideHeader=false; + /** + * @var boolean whether to leverage the {@link https://developer.mozilla.org/en/DOM/window.history DOM history object}. Set this property to true + * to persist state of grid across page revisits. Note, there are two limitations for this feature: + *
                + *
              • this feature is only compatible with browsers that support HTML5.
              • + *
              • expect unexpected functionality (e.g. multiple ajax calls) if there is more than one grid/list on a single page with enableHistory turned on.
              • + *
              + * @since 1.1.11 + */ + public $enableHistory=false; + + + /** + * Initializes the grid view. + * This method will initialize required property values and instantiate {@link columns} objects. + */ + public function init() + { + parent::init(); + + if(empty($this->updateSelector)) + throw new CException(Yii::t('zii','The property updateSelector should be defined.')); + if(empty($this->filterSelector)) + throw new CException(Yii::t('zii','The property filterSelector should be defined.')); + + if(!isset($this->htmlOptions['class'])) + $this->htmlOptions['class']='grid-view'; + + if($this->baseScriptUrl===null) + $this->baseScriptUrl=Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('zii.widgets.assets')).'/gridview'; + + if($this->cssFile!==false) + { + if($this->cssFile===null) + $this->cssFile=$this->baseScriptUrl.'/styles.css'; + Yii::app()->getClientScript()->registerCssFile($this->cssFile); + } + + $this->initColumns(); + } + + /** + * Creates column objects and initializes them. + */ + protected function initColumns() + { + if($this->columns===array()) + { + if($this->dataProvider instanceof CActiveDataProvider) + $this->columns=$this->dataProvider->model->attributeNames(); + elseif($this->dataProvider instanceof IDataProvider) + { + // use the keys of the first row of data as the default columns + $data=$this->dataProvider->getData(); + if(isset($data[0]) && is_array($data[0])) + $this->columns=array_keys($data[0]); + } + } + $id=$this->getId(); + foreach($this->columns as $i=>$column) + { + if(is_string($column)) + $column=$this->createDataColumn($column); + else + { + if(!isset($column['class'])) + $column['class']='CDataColumn'; + $column=Yii::createComponent($column, $this); + } + if(!$column->visible) + { + unset($this->columns[$i]); + continue; + } + if($column->id===null) + $column->id=$id.'_c'.$i; + $this->columns[$i]=$column; + } + + foreach($this->columns as $column) + $column->init(); + } + + /** + * Creates a {@link CDataColumn} based on a shortcut column specification string. + * @param string $text the column specification string + * @return CDataColumn the column instance + */ + protected function createDataColumn($text) + { + if(!preg_match('/^([\w\.]+)(:(\w*))?(:(.*))?$/',$text,$matches)) + throw new CException(Yii::t('zii','The column must be specified in the format of "Name:Type:Label", where "Type" and "Label" are optional.')); + $column=new CDataColumn($this); + $column->name=$matches[1]; + if(isset($matches[3]) && $matches[3]!=='') + $column->type=$matches[3]; + if(isset($matches[5])) + $column->header=$matches[5]; + return $column; + } + + /** + * Registers necessary client scripts. + */ + public function registerClientScript() + { + $id=$this->getId(); + + if($this->ajaxUpdate===false) + $ajaxUpdate=false; + else + $ajaxUpdate=array_unique(preg_split('/\s*,\s*/',$this->ajaxUpdate.','.$id,-1,PREG_SPLIT_NO_EMPTY)); + $options=array( + 'ajaxUpdate'=>$ajaxUpdate, + 'ajaxVar'=>$this->ajaxVar, + 'pagerClass'=>$this->pagerCssClass, + 'loadingClass'=>$this->loadingCssClass, + 'filterClass'=>$this->filterCssClass, + 'tableClass'=>$this->itemsCssClass, + 'selectableRows'=>$this->selectableRows, + 'enableHistory'=>$this->enableHistory, + 'updateSelector'=>$this->updateSelector, + 'filterSelector'=>$this->filterSelector + ); + if($this->ajaxUrl!==null) + $options['url']=CHtml::normalizeUrl($this->ajaxUrl); + if($this->ajaxType!==null) + $options['ajaxType']=strtoupper($this->ajaxType); + if($this->enablePagination) + $options['pageVar']=$this->dataProvider->getPagination()->pageVar; + foreach(array('beforeAjaxUpdate', 'afterAjaxUpdate', 'ajaxUpdateError', 'selectionChanged') as $event) + { + if($this->$event!==null) + { + if($this->$event instanceof CJavaScriptExpression) + $options[$event]=$this->$event; + else + $options[$event]=new CJavaScriptExpression($this->$event); + } + } + + $options=CJavaScript::encode($options); + $cs=Yii::app()->getClientScript(); + $cs->registerCoreScript('jquery'); + $cs->registerCoreScript('bbq'); + if($this->enableHistory) + $cs->registerCoreScript('history'); + $cs->registerScriptFile($this->baseScriptUrl.'/jquery.yiigridview.js',CClientScript::POS_END); + $cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiGridView($options);"); + } + + /** + * Renders the data items for the grid view. + */ + public function renderItems() + { + if($this->dataProvider->getItemCount()>0 || $this->showTableOnEmpty) + { + echo "itemsCssClass}\">\n"; + $this->renderTableHeader(); + ob_start(); + $this->renderTableBody(); + $body=ob_get_clean(); + $this->renderTableFooter(); + echo $body; // TFOOT must appear before TBODY according to the standard. + echo "
              "; + } + else + $this->renderEmptyText(); + } + + /** + * Renders the table header. + */ + public function renderTableHeader() + { + if(!$this->hideHeader) + { + echo "\n"; + + if($this->filterPosition===self::FILTER_POS_HEADER) + $this->renderFilter(); + + echo "\n"; + foreach($this->columns as $column) + $column->renderHeaderCell(); + echo "\n"; + + if($this->filterPosition===self::FILTER_POS_BODY) + $this->renderFilter(); + + echo "\n"; + } + elseif($this->filter!==null && ($this->filterPosition===self::FILTER_POS_HEADER || $this->filterPosition===self::FILTER_POS_BODY)) + { + echo "\n"; + $this->renderFilter(); + echo "\n"; + } + } + + /** + * Renders the filter. + * @since 1.1.1 + */ + public function renderFilter() + { + if($this->filter!==null) + { + echo "filterCssClass}\">\n"; + foreach($this->columns as $column) + $column->renderFilterCell(); + echo "\n"; + } + } + + /** + * Renders the table footer. + */ + public function renderTableFooter() + { + $hasFilter=$this->filter!==null && $this->filterPosition===self::FILTER_POS_FOOTER; + $hasFooter=$this->getHasFooter(); + if($hasFilter || $hasFooter) + { + echo "\n"; + if($hasFooter) + { + echo "\n"; + foreach($this->columns as $column) + $column->renderFooterCell(); + echo "\n"; + } + if($hasFilter) + $this->renderFilter(); + echo "\n"; + } + } + + /** + * Renders the table body. + */ + public function renderTableBody() + { + $data=$this->dataProvider->getData(); + $n=count($data); + echo "\n"; + + if($n>0) + { + for($row=0;$row<$n;++$row) + $this->renderTableRow($row); + } + else + { + echo ''; + $this->renderEmptyText(); + echo "\n"; + } + echo "\n"; + } + + /** + * Renders a table body row. + * @param integer $row the row number (zero-based). + */ + public function renderTableRow($row) + { + $htmlOptions=array(); + if($this->rowHtmlOptionsExpression!==null) + { + $data=$this->dataProvider->data[$row]; + $options=$this->evaluateExpression($this->rowHtmlOptionsExpression,array('row'=>$row,'data'=>$data)); + if(is_array($options)) + $htmlOptions = $options; + } + + if($this->rowCssClassExpression!==null) + { + $data=$this->dataProvider->data[$row]; + $class=$this->evaluateExpression($this->rowCssClassExpression,array('row'=>$row,'data'=>$data)); + } + elseif(is_array($this->rowCssClass) && ($n=count($this->rowCssClass))>0) + $class=$this->rowCssClass[$row%$n]; + + if(!empty($class)) + { + if(isset($htmlOptions['class'])) + $htmlOptions['class'].=' '.$class; + else + $htmlOptions['class']=$class; + } + + echo CHtml::openTag('tr', $htmlOptions)."\n"; + foreach($this->columns as $column) + $column->renderDataCell($row); + echo "\n"; + } + + /** + * @return boolean whether the table should render a footer. + * This is true if any of the {@link columns} has a true {@link CGridColumn::hasFooter} value. + */ + public function getHasFooter() + { + foreach($this->columns as $column) + if($column->getHasFooter()) + return true; + return false; + } + + /** + * @return CFormatter the formatter instance. Defaults to the 'format' application component. + */ + public function getFormatter() + { + if($this->_formatter===null) + $this->_formatter=Yii::app()->format; + return $this->_formatter; + } + + /** + * @param CFormatter $value the formatter instance + */ + public function setFormatter($value) + { + $this->_formatter=$value; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CLinkColumn.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CLinkColumn.php new file mode 100644 index 0000000..edc0d71 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/grid/CLinkColumn.php @@ -0,0 +1,111 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.grid.CGridColumn'); + +/** + * CLinkColumn represents a grid view column that renders a hyperlink in each of its data cells. + * + * The {@link label} and {@link url} properties determine how each hyperlink will be rendered. + * The {@link labelExpression}, {@link urlExpression} properties may be used instead if they are available. + * In addition, if {@link imageUrl} is set, an image link will be rendered. + * + * @author Qiang Xue + * @package zii.widgets.grid + * @since 1.1 + */ +class CLinkColumn extends CGridColumn +{ + /** + * @var string the label to the hyperlinks in the data cells. Note that the label will not + * be HTML-encoded when rendering. This property is ignored if {@link labelExpression} is set. + * @see labelExpression + */ + public $label='Link'; + /** + * @var string a PHP expression that will be evaluated for every data cell and whose result will be rendered + * as the label of the hyperlink of the data cell. + * In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based).
              • + *
              • $data the data model for the row.
              • + *
              • $this the column object.
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + */ + public $labelExpression; + /** + * @var string the URL to the image. If this is set, an image link will be rendered. + */ + public $imageUrl; + /** + * @var string the URL of the hyperlinks in the data cells. + * This property is ignored if {@link urlExpression} is set. + * @see urlExpression + */ + public $url='javascript:void(0)'; + /** + * @var string a PHP expression that will be evaluated for every data cell and whose result will be rendered + * as the URL of the hyperlink of the data cells. + * In this expression, you can use the following variables: + *
                + *
              • $row the row number (zero-based).
              • + *
              • $data the data model for the row.
              • + *
              • $this the column object.
              • + *
              + * The PHP expression will be evaluated using {@link evaluateExpression}. + * + * A PHP expression can be any PHP code that has a value. To learn more about what an expression is, + * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}. + */ + public $urlExpression; + /** + * @var array the HTML options for the data cell tags. + */ + public $htmlOptions=array('class'=>'link-column'); + /** + * @var array the HTML options for the header cell tag. + */ + public $headerHtmlOptions=array('class'=>'link-column'); + /** + * @var array the HTML options for the footer cell tag. + */ + public $footerHtmlOptions=array('class'=>'link-column'); + /** + * @var array the HTML options for the hyperlinks + */ + public $linkHtmlOptions=array(); + + /** + * Renders the data cell content. + * This method renders a hyperlink in the data cell. + * @param integer $row the row number (zero-based) + * @param mixed $data the data associated with the row + */ + protected function renderDataCellContent($row,$data) + { + if($this->urlExpression!==null) + $url=$this->evaluateExpression($this->urlExpression,array('data'=>$data,'row'=>$row)); + else + $url=$this->url; + if($this->labelExpression!==null) + $label=$this->evaluateExpression($this->labelExpression,array('data'=>$data,'row'=>$row)); + else + $label=$this->label; + $options=$this->linkHtmlOptions; + if(is_string($this->imageUrl)) + echo CHtml::link(CHtml::image($this->imageUrl,$label),$url,$options); + else + echo CHtml::link($label,$url,$options); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiAccordion.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiAccordion.php new file mode 100644 index 0000000..818bd7e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiAccordion.php @@ -0,0 +1,95 @@ + + * @author Qiang Xue + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiAccordion displays an accordion widget. + * + * CJuiAccordion encapsulates the {@link http://jqueryui.com/accordion/ JUI Accordion} + * plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiAccordion',array(
              + *     'panels'=>array(
              + *         'panel 1'=>'content for panel 1',
              + *         'panel 2'=>'content for panel 2',
              + *         // panel 3 contains the content rendered by a partial view
              + *         'panel 3'=>$this->renderPartial('_partial',null,true),
              + *     ),
              + *     // additional javascript options for the accordion plugin
              + *     'options'=>array(
              + *         'animated'=>'bounceslide',
              + *     ),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI accordion plugin. Please refer to + * the {@link http://api.jqueryui.com/accordion/ JUI Accordion API} + * documentation for possible options (name-value pairs) and + * {@link http://jqueryui.com/accordion/ JUI Accordion page} for general + * description and demo. + * + * @author Sebastian Thierer + * @author Qiang Xue + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiAccordion extends CJuiWidget +{ + /** + * @var array list of panels (panel title=>panel content). + * Note that neither panel title nor panel content will be HTML-encoded. + */ + public $panels=array(); + /** + * @var string the name of the container element that contains all panels. Defaults to 'div'. + */ + public $tagName='div'; + /** + * @var string the template that is used to generated every panel header. + * The token "{title}" in the template will be replaced with the panel title. + * Note that if you make change to this template, you may also need to adjust + * the 'header' setting in {@link options}. + */ + public $headerTemplate='

              {title}

              '; + /** + * @var string the template that is used to generated every panel content. + * The token "{content}" in the template will be replaced with the panel content. + */ + public $contentTemplate='
              {content}
              '; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + foreach($this->panels as $title=>$content) + { + echo strtr($this->headerTemplate,array('{title}'=>$title))."\n"; + echo strtr($this->contentTemplate,array('{content}'=>$content))."\n"; + } + echo CHtml::closeTag($this->tagName); + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').accordion($options);"); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiAutoComplete.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiAutoComplete.php new file mode 100644 index 0000000..204dd25 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiAutoComplete.php @@ -0,0 +1,97 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiInputWidget'); + +/** + * CJuiAutoComplete displays an autocomplete field. + * + * CJuiAutoComplete encapsulates the {@link http://jqueryui.com/autocomplete/ JUI + * autocomplete} plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiAutoComplete',array(
              + *     'name'=>'city',
              + *     'source'=>array('ac1','ac2','ac3'),
              + *     // additional javascript options for the autocomplete plugin
              + *     'options'=>array(
              + *         'minLength'=>'2',
              + *     ),
              + *     'htmlOptions'=>array(
              + *         'style'=>'height:20px;',
              + *     ),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI autocomplete plugin. Please refer to + * the {@link http://api.jqueryui.com/autocomplete/ JUI AutoComplete API} + * documentation for possible options (name-value pairs) and + * {@link http://jqueryui.com/autocomplete/ JUI AutoComplete page} for + * general description and demo. + * + * By configuring the {@link source} property, you may specify where to search + * the autocomplete options for each item. If source is an array, the list is + * used for autocomplete. You may also configure {@link sourceUrl} to retrieve + * autocomplete items from an ajax response. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1.2 + */ +class CJuiAutoComplete extends CJuiInputWidget +{ + /** + * @var mixed the entries that the autocomplete should choose from. This can be + *
                + *
              • an Array with local data
              • + *
              • a String, specifying a URL that returns JSON data as the entries.
              • + *
              • a javascript callback. Please make sure you wrap the callback with + * {@link CJavaScriptExpression} in this case.
              • + *
              + */ + public $source=array(); + /** + * @var mixed the URL that will return JSON data as the autocomplete items. + * CHtml::normalizeUrl() will be applied to this property to convert the property + * into a proper URL. When this property is set, the {@link source} property will be ignored. + */ + public $sourceUrl; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + list($name,$id)=$this->resolveNameID(); + + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + if(isset($this->htmlOptions['name'])) + $name=$this->htmlOptions['name']; + + if($this->hasModel()) + echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions); + else + echo CHtml::textField($name,$this->value,$this->htmlOptions); + + if($this->sourceUrl!==null) + $this->options['source']=CHtml::normalizeUrl($this->sourceUrl); + else + $this->options['source']=$this->source; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').autocomplete($options);"); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiButton.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiButton.php new file mode 100644 index 0000000..db14f1b --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiButton.php @@ -0,0 +1,173 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiInputWidget'); + +/** + * CJuiButton displays a button widget. + * + * CJuiButton encapsulates the {@link http://jqueryui.com/button/ JUI Button} + * plugin. + * + * To use this widget as a submit button, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiButton',array(
              + *     'name'=>'submit',
              + *     'caption'=>'Save',
              + *     'options'=>array(
              + *         'onclick'=>new CJavaScriptExpression('function(){alert("Yes");}'),
              + *     ),
              + * ));
              + * 
              + * + * To use this widget as a button, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiButton',array(
              + *     'name'=>'button',
              + *     'caption'=>'Save',
              + *     'value'=>'asd',
              + *     'onclick'=>new CJavaScriptExpression('function(){alert("Save button clicked"); this.blur(); return false;}'),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI button plugin. Please refer to + * the {@link http://api.jqueryui.com/button/ JUI Button API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/button/ JUI Button page} for general description + * and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1.3 + */ +class CJuiButton extends CJuiInputWidget +{ + /** + * @var string The button type (possible types: submit, button, link, radio, checkbox, buttonset). + * "submit" is used as default. + */ + public $buttonType='submit'; + /** + * @var string The default html tag for the buttonset + */ + public $htmlTag='div'; + /** + * @var mixed a URL or an action route that can be used to create a URL. Used when a buttonType "link" is selected. + * See {@link normalizeUrl} for more details about how to specify this parameter. + */ + public $url=null; + /** + * @var mixed The value of the current item. Used only for "radio" and "checkbox" + */ + public $value; + /** + * @var string The button text + */ + public $caption=""; + /** + * @var string The javascript function to be raised when this item is clicked (client event). + */ + public $onclick; + + /** + * (non-PHPdoc) + * @see framework/zii/widgets/jui/CJuiWidget::init() + */ + public function init() + { + parent::init(); + + if($this->buttonType=='buttonset') + { + if(!isset($this->htmlOptions['id'])) + $this->htmlOptions['id']=$this->getId(); + + echo CHtml::openTag($this->htmlTag,$this->htmlOptions); + } + } + + /** + * (non-PHPdoc) + * @see framework/CWidget::run() + */ + public function run() + { + $cs=Yii::app()->getClientScript(); + list($name,$id)=$this->resolveNameID(); + + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + if(isset($this->htmlOptions['name'])) + $name=$this->htmlOptions['name']; + else + $this->htmlOptions['name']=$name; + + if($this->buttonType=='buttonset') + { + echo CHtml::closeTag($this->htmlTag); + $cs->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').buttonset();"); + } + else + { + switch($this->buttonType) + { + case 'submit': + echo CHtml::submitButton($this->caption,$this->htmlOptions)."\n"; + break; + case 'button': + echo CHtml::htmlButton($this->caption,$this->htmlOptions)."\n"; + break; + case 'link': + echo CHtml::link($this->caption,$this->url,$this->htmlOptions)."\n"; + break; + case 'radio': + if($this->hasModel()) + { + echo CHtml::activeRadioButton($this->model,$this->attribute,$this->htmlOptions); + echo CHtml::label($this->caption,CHtml::activeId($this->model,$this->attribute))."\n"; + } + else + { + echo CHtml::radioButton($name,$this->value,$this->htmlOptions); + echo CHtml::label($this->caption,$id)."\n"; + } + break; + case 'checkbox': + if($this->hasModel()) + { + echo CHtml::activeCheckbox($this->model,$this->attribute,$this->htmlOptions); + echo CHtml::label($this->caption,CHtml::activeId($this->model,$this->attribute))."\n"; + } + else + { + echo CHtml::checkbox($name,$this->value,$this->htmlOptions); + echo CHtml::label($this->caption,$id)."\n"; + } + break; + default: + throw new CException(Yii::t('zii','The button type "{type}" is not supported.',array('{type}'=>$this->buttonType))); + } + + $options=CJavaScript::encode($this->options); + if($this->onclick!==null) + { + if(!($this->onclick instanceof CJavaScriptExpression)) + $this->onclick=new CJavaScriptExpression($this->onclick); + $click=CJavaScript::encode($this->onclick); + $cs->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').button($options).click($click);"); + } + else + $cs->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').button($options);"); + } + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDatePicker.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDatePicker.php new file mode 100644 index 0000000..0456429 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDatePicker.php @@ -0,0 +1,128 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiInputWidget'); + +/** + * CJuiDatePicker displays a datepicker. + * + * CJuiDatePicker encapsulates the {@link http://jqueryui.com/datepicker/ JUI + * datepicker} plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiDatePicker',array(
              + *     'name'=>'publishDate',
              + *     // additional javascript options for the date picker plugin
              + *     'options'=>array(
              + *         'showAnim'=>'fold',
              + *     ),
              + *     'htmlOptions'=>array(
              + *         'style'=>'height:20px;'
              + *     ),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI datepicker plugin. Please refer to + * the {@link http://api.jqueryui.com/datepicker/ JUI DatePicker API} + * documentation for possible options (name-value pairs) and + * {@link http://jqueryui.com/datepicker/ JUI DatePicker page} for general + * description and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiDatePicker extends CJuiInputWidget +{ + /** + * @var string the locale ID (eg 'fr', 'de') for the language to be used by the date picker. + * If this property is not set, I18N will not be involved. That is, the date picker will show in English. + * You can force English language by setting the language attribute as '' (empty string) + */ + public $language; + /** + * @var string The i18n Jquery UI script file. It uses scriptUrl property as base url. + */ + public $i18nScriptFile='jquery-ui-i18n.min.js'; + /** + * @var array The default options called just one time per request. This options will alter every other CJuiDatePicker instance in the page. + * It has to be set at the first call of CJuiDatePicker widget in the request. + */ + public $defaultOptions; + /** + * @var boolean If true, shows the widget as an inline calendar and the input as a hidden field. + */ + public $flat=false; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + list($name,$id)=$this->resolveNameID(); + + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + if(isset($this->htmlOptions['name'])) + $name=$this->htmlOptions['name']; + + if($this->flat===false) + { + if($this->hasModel()) + echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions); + else + echo CHtml::textField($name,$this->value,$this->htmlOptions); + } + else + { + if($this->hasModel()) + { + echo CHtml::activeHiddenField($this->model,$this->attribute,$this->htmlOptions); + $attribute=$this->attribute; + $this->options['defaultDate']=$this->model->$attribute; + } + else + { + echo CHtml::hiddenField($name,$this->value,$this->htmlOptions); + $this->options['defaultDate']=$this->value; + } + + $this->options['altField']='#'.$id; + + $id=$this->htmlOptions['id']=$id.'_container'; + $this->htmlOptions['name']=$name.'_container'; + + echo CHtml::tag('div',$this->htmlOptions,''); + } + + $options=CJavaScript::encode($this->options); + $js = "jQuery('#{$id}').datepicker($options);"; + + if($this->language!='' && $this->language!='en') + { + $this->registerScriptFile($this->i18nScriptFile); + $js = "jQuery('#{$id}').datepicker(jQuery.extend({showMonthAfterYear:false},jQuery.datepicker.regional['{$this->language}'],{$options}));"; + } + + $cs = Yii::app()->getClientScript(); + + if(isset($this->defaultOptions)) + { + $this->registerScriptFile($this->i18nScriptFile); + $cs->registerScript(__CLASS__,$this->defaultOptions!==null?'jQuery.datepicker.setDefaults('.CJavaScript::encode($this->defaultOptions).');':''); + } + $cs->registerScript(__CLASS__.'#'.$id,$js); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDialog.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDialog.php new file mode 100644 index 0000000..5bd9efc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDialog.php @@ -0,0 +1,85 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiDialog displays a dialog widget. + * + * CJuiDialog encapsulates the {@link http://jqueryui.com/dialog/ JUI Dialog} + * plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->beginWidget('zii.widgets.jui.CJuiDialog',array(
              + *     'id'=>'mydialog',
              + *     // additional javascript options for the dialog plugin
              + *     'options'=>array(
              + *         'title'=>'Dialog box 1',
              + *         'autoOpen'=>false,
              + *     ),
              + * ));
              + *
              + *     echo 'dialog content here';
              + *
              + * $this->endWidget('zii.widgets.jui.CJuiDialog');
              + *
              + * // the link that may open the dialog
              + * echo CHtml::link('open dialog', '#', array(
              + *    'onclick'=>'$("#mydialog").dialog("open"); return false;',
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI dialog plugin. Please refer to + * the {@link http://api.jqueryui.com/dialog/ JUI Dialog API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/dialog/ JUI Dialog page} for general description + * and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiDialog extends CJuiWidget +{ + /** + * @var string the name of the container element that contains all panels. Defaults to 'div'. + */ + public $tagName='div'; + + /** + * Renders the open tag of the dialog. + * This method also registers the necessary javascript code. + */ + public function init() + { + parent::init(); + + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').dialog($options);"); + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + } + + /** + * Renders the close tag of the dialog. + */ + public function run() + { + echo CHtml::closeTag($this->tagName); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDraggable.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDraggable.php new file mode 100644 index 0000000..640c5c7 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDraggable.php @@ -0,0 +1,78 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiDraggable displays a draggable widget. + * + * CJuiDraggable encapsulates the {@link http://jqueryui.com/draggable/ JUI Draggable} + * plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->beginWidget('zii.widgets.jui.CJuiDraggable',array(
              + *     // additional javascript options for the draggable plugin
              + *     'options'=>array(
              + *         'scope'=>'myScope',
              + *     ),
              + * ));
              + *     echo 'Your draggable content here';
              + *
              + * $this->endWidget();
              + *
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI Draggable plugin. Please refer to + * the {@link http://api.jqueryui.com/draggable/ JUI Draggable API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/draggable/ JUI Draggable page} for general + * description and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiDraggable extends CJuiWidget +{ + /** + * @var string the name of the Draggable element. Defaults to 'div'. + */ + public $tagName='div'; + + /** + * Renders the open tag of the draggable element. + * This method also registers the necessary javascript code. + */ + public function init() + { + parent::init(); + + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').draggable($options);"); + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + } + + /** + * Renders the close tag of the draggable element. + */ + public function run() + { + echo CHtml::closeTag($this->tagName); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDroppable.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDroppable.php new file mode 100644 index 0000000..cafb3fb --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiDroppable.php @@ -0,0 +1,78 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiDroppable displays a droppable widget. + * + * CJuiDroppable encapsulates the {@link http://jqueryui.com/droppable/ JUI Droppable} + * plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->beginWidget('zii.widgets.jui.CJuiDroppable',array(
              + *     // additional javascript options for the droppable plugin
              + *     'options'=>array(
              + *         'scope'=>'myScope',
              + *     ),
              + * ));
              + *     echo 'Your droppable content here';
              + *
              + * $this->endWidget();
              + *
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI Droppable plugin. Please refer to + * the {@link http://api.jqueryui.com/droppable/ JUI Droppable API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/droppable/ JUI Droppable page} for general + * description and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiDroppable extends CJuiWidget +{ + /** + * @var string the HTML tag name of the Droppable element. Defaults to 'div'. + */ + public $tagName='div'; + + /** + * Renders the open tag of the droppable element. + * This method also registers the necessary javascript code. + */ + public function init() + { + parent::init(); + + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').droppable($options);"); + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + } + + /** + * Renders the close tag of the droppable element. + */ + public function run() + { + echo CHtml::closeTag($this->tagName); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiInputWidget.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiInputWidget.php new file mode 100644 index 0000000..77f7414 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiInputWidget.php @@ -0,0 +1,80 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiInputWidget is the base class for JUI widgets that can collect user input. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +abstract class CJuiInputWidget extends CJuiWidget +{ + /** + * @var CModel the data model associated with this widget. + */ + public $model; + /** + * @var string the attribute associated with this widget. + * The name can contain square brackets (e.g. 'name[1]') which is used to collect tabular data input. + */ + public $attribute; + /** + * @var string the input name. This must be set if {@link model} is not set. + */ + public $name; + /** + * @var string the input value. + */ + public $value; + + /** + * Resolves name and ID of the input. Source property of the name and/or source property of the attribute + * could be customized by specifying first and/or second parameter accordingly. + * @param string $nameProperty class property name which holds element name to be used. This parameter + * is available since 1.1.14. + * @param string $attributeProperty class property name which holds model attribute name to be used. This + * parameter is available since 1.1.14. + * @return array name and ID of the input: array('name','id'). + * @throws CException in case model and attribute property or name property cannot be resolved. + */ + protected function resolveNameID($nameProperty='name',$attributeProperty='attribute') + { + if($this->$nameProperty!==null) + $name=$this->$nameProperty; + elseif(isset($this->htmlOptions[$nameProperty])) + $name=$this->htmlOptions[$nameProperty]; + elseif($this->hasModel()) + $name=CHtml::activeName($this->model,$this->$attributeProperty); + else + throw new CException(Yii::t('zii','{class} must specify "model" and "{attribute}" or "{name}" property values.', + array('{class}'=>get_class($this),'{attribute}'=>$attributeProperty,'{name}'=>$nameProperty))); + + if(($id=$this->getId(false))===null) + { + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $id=CHtml::getIdByName($name); + } + + return array($name,$id); + } + + /** + * @return boolean whether this widget is associated with a data model. + */ + protected function hasModel() + { + return $this->model instanceof CModel && $this->attribute!==null; + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiProgressBar.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiProgressBar.php new file mode 100644 index 0000000..daf4f33 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiProgressBar.php @@ -0,0 +1,74 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiProgressBar displays a progress bar widget. + * + * CJuiProgressBar encapsulates the {@link http://jqueryui.com/progressbar/ JUI + * Progressbar} plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiProgressBar',array(
              + *     'value'=>75,
              + *     // additional javascript options for the progress bar plugin
              + *     'options'=>array(
              + *         'change'=>new CJavaScriptExpression('function(event, ui) {...}'),
              + *     ),
              + *     'htmlOptions'=>array(
              + *         'style'=>'height:20px;',
              + *     ),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI progressbar plugin. Please refer to + * the {@link http://api.jqueryui.com/progressbar/ JUI ProgressBar} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/progressbar/ JUI ProgressBar page} for general + * description and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiProgressBar extends CJuiWidget +{ + /** + * @var string the name of the container element that contains the progress bar. Defaults to 'div'. + */ + public $tagName='div'; + /** + * @var integer the percentage of the progress. This must be an integer between 0 and 100. Defaults to 0. + */ + public $value=0; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + echo CHtml::openTag($this->tagName,$this->htmlOptions); + echo CHtml::closeTag($this->tagName); + + $this->options['value']=$this->value; + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').progressbar($options);"); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiResizable.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiResizable.php new file mode 100644 index 0000000..b8964f4 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiResizable.php @@ -0,0 +1,78 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiResizable displays a resizable widget. + * + * CJuiResizable encapsulates the {@link http://jqueryui.com/resizable/ JUI Resizable} + * plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->beginWidget('zii.widgets.jui.CJuiResizable',array(
              + *     // additional javascript options for the resizable plugin
              + *     'options'=>array(
              + *         'minHeight'=>'150',
              + *     ),
              + * ));
              + *     echo 'Your Resizable content here';
              + *
              + * $this->endWidget();
              + *
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI Resizable plugin. Please refer to + * the {@link http://api.jqueryui.com/resizable/ JUI Resizable API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/resizable/ JUI Resizable page} for general + * description and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiResizable extends CJuiWidget +{ + /** + * @var string the name of the Resizable element. Defaults to 'div'. + */ + public $tagName='div'; + + /** + * Renders the open tag of the resizable element. + * This method also registers the necessary javascript code. + */ + public function init() + { + parent::init(); + + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').resizable($options);"); + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + } + + /** + * Renders the close tag of the resizable element. + */ + public function run() + { + echo CHtml::closeTag($this->tagName); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSelectable.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSelectable.php new file mode 100644 index 0000000..75fb4da --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSelectable.php @@ -0,0 +1,82 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiSelectable displays an accordion widget. + * + * CJuiSelectable encapsulates the {@link http://jqueryui.com/selectable/ JUI Selectable} + * plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiSelectable',array(
              + *     'items'=>array(
              + *         'id1'=>'Item 1',
              + *         'id2'=>'Item 2',
              + *         'id3'=>'Item 3',
              + *     ),
              + *     // additional javascript options for the selectable plugin
              + *     'options'=>array(
              + *         'delay'=>'300',
              + *     ),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI Selectable plugin. Please refer to + * the {@link http://api.jqueryui.com/selectable/ JUI Selectable API} + * documentation for possible options (name-value pairs) and + * {@link http://jqueryui.com/selectable/ JUI Selectable page} for general + * description and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiSelectable extends CJuiWidget { + /** + * @var array list of selectable items (id=>item content). + * Note that the item contents will not be HTML-encoded. + */ + public $items=array(); + /** + * @var string the name of the container element that contains all items. Defaults to 'ol'. + */ + public $tagName='ol'; + /** + * @var string the template that is used to generated every selectable item. + * The token "{content}" in the template will be replaced with the item content, + * while "{id}" will be replaced with the item ID. + */ + public $itemTemplate='
            • {content}
            • '; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').selectable({$options});"); + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + foreach($this->items as $id=>$content) + echo strtr($this->itemTemplate,array('{id}'=>$id,'{content}'=>$content))."\n"; + echo CHtml::closeTag($this->tagName); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSlider.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSlider.php new file mode 100644 index 0000000..a8b78de --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSlider.php @@ -0,0 +1,76 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiSlider displays a slider. + * + * CJuiSlider encapsulates the {@link http://jqueryui.com/slider/ JUI + * slider} plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiSlider',array(
              + *     'value'=>37,
              + *     // additional javascript options for the slider plugin
              + *     'options'=>array(
              + *         'min'=>10,
              + *         'max'=>50,
              + *     ),
              + *     'htmlOptions'=>array(
              + *         'style'=>'height:20px;',
              + *     ),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI slider plugin. Please refer to + * the {@link http://api.jqueryui.com/slider/ JUI Slider API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/slider/ JUI Slider page} for general + * description and demo. + * + * @author Qiang Xue + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiSlider extends CJuiWidget +{ + /** + * @var string the name of the container element that contains the slider. Defaults to 'div'. + */ + public $tagName='div'; + /** + * @var integer determines the value of the slider, if there's only one handle. If there is more than one handle, determines the value of the first handle. + */ + public $value; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + echo CHtml::tag($this->tagName,$this->htmlOptions,''); + + if($this->value!==null) + $this->options['value']=$this->value; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').slider($options);"); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSliderInput.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSliderInput.php new file mode 100644 index 0000000..0ff7a4f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSliderInput.php @@ -0,0 +1,168 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiInputWidget'); + +/** + * CJuiSliderInput displays a slider. It can be used in forms and post its value. + * + * CJuiSlider encapsulates the {@link http://jqueryui.com/slider/ JUI + * slider} plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiSliderInput',array(
              + *     'name'=>'rate',
              + *     'value'=>37,
              + *     // additional javascript options for the slider plugin
              + *     'options'=>array(
              + *         'min'=>10,
              + *         'max'=>50,
              + *     ),
              + *     'htmlOptions'=>array(
              + *         'style'=>'height:20px;',
              + *     ),
              + * ));
              + * 
              + * + * The widget can also be used in range mode which uses 2 sliders to set a range. + * In this mode, {@link attribute} and {@link maxAttribute} will define the attribute + * names for the minimum and maximum range values, respectively. For example: + * + *
              + * $this->widget('zii.widgets.jui.CJuiSliderInput',array(
              + *     'model'=>$model,
              + *     'attribute'=>'timeMin',
              + *     'maxAttribute'=>'timeMax',
              + *     // additional javascript options for the slider plugin
              + *     'options'=>array(
              + *         'range'=>true,
              + *         'min'=>0,
              + *         'max'=>24,
              + *     ),
              + * ));
              + * 
              + * + * If you need to use the slider event, please change the event value for 'stop' or 'change'. + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI slider plugin. Please refer to + * the {@link http://api.jqueryui.com/slider/ JUI Slider API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/slider/ JUI Slider page} for general + * description and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiSliderInput extends CJuiInputWidget +{ + /** + * @var string the name of the container element that contains the slider. Defaults to 'div'. + */ + public $tagName='div'; + /** + * @var integer determines the value of the slider, if there's only one handle. If there is more than one handle, + * determines the value of the first handle. + */ + public $value; + /** + * @var string the name of the event where the input will be attached to the slider. It + * can be 'slide', 'stop' or 'change'. If you want to use 'slide' event change $event property to 'change'. + */ + public $event='slide'; + /** + * @var string name of attribute for max value if slider is used in range mode. + */ + public $maxAttribute; + /** + * @var string the input name to be used for max value attribute when using slider in range mode. + * This must be set in case {@link model} isn't used. + * @since 1.1.14 + */ + public $maxName; + /** + * @var integer determines the max value of the slider, if there's two handles (range mode). Ignored if there's + * only one handle. + * @since 1.1.14 + */ + public $maxValue; + /** + * @var string the suffix to be appended to the ID of the max value input element + * when slider used in range mode. + * @since 1.1.14 + */ + public $maxIdSuffix='_end'; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + list($name,$id)=$this->resolveNameID(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + $isRange=isset($this->options['range']) && $this->options['range'] && + $this->options['range']!=='max' && $this->options['range']!=='min'; + + if($this->hasModel()) + { + $attribute=$this->attribute; + if($isRange) + { + $options=$this->htmlOptions; + echo CHtml::activeHiddenField($this->model,$this->attribute,$options); + $options['id'].=$this->maxIdSuffix; + echo CHtml::activeHiddenField($this->model,$this->maxAttribute,$options); + $maxAttribute=$this->maxAttribute; + $this->options['values']=array($this->model->$attribute,$this->model->$maxAttribute); + } + else + { + echo CHtml::activeHiddenField($this->model,$this->attribute,$this->htmlOptions); + $this->options['value']=$this->model->$attribute; + } + } + else + { + if($isRange) + { + list($maxName,$maxId)=$this->resolveNameID('maxName','maxAttribute'); + $options=$this->htmlOptions; + echo CHtml::hiddenField($name,$this->value,$options); + $options['id'].=$this->maxIdSuffix; + echo CHtml::hiddenField($maxName,$this->maxValue,$options); + $this->options['values']=array($this->value,$this->maxValue); + } + else + { + echo CHtml::hiddenField($name,$this->value,$this->htmlOptions); + if($this->value!==null) + $this->options['value']=$this->value; + } + } + + $idHidden=$this->htmlOptions['id']; + $this->htmlOptions['id']=$idHidden.'_slider'; + echo CHtml::tag($this->tagName,$this->htmlOptions,''); + + $this->options[$this->event]=$isRange + ? new CJavaScriptExpression("function(e,ui){ v=ui.values; jQuery('#{$idHidden}').val(v[0]); jQuery('#{$idHidden}{$this->maxIdSuffix}').val(v[1]); }") + : new CJavaScriptExpression("function(event, ui) { jQuery('#{$idHidden}').val(ui.value); }"); + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}_slider').slider($options);"); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSortable.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSortable.php new file mode 100644 index 0000000..7a34f32 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiSortable.php @@ -0,0 +1,86 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiSortable makes selected elements sortable by dragging with the mouse. + * + * CJuiSortable encapsulates the {@link http://jqueryui.com/sortable/ JUI Sortable} + * plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiSortable',array(
              + *     'items'=>array(
              + *         'id1'=>'Item 1',
              + *         'id2'=>'Item 2',
              + *         'id3'=>'Item 3',
              + *     ),
              + *     // additional javascript options for the JUI Sortable plugin
              + *     'options'=>array(
              + *         'delay'=>'300',
              + *     ),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI Sortable plugin. Please refer to + * the {@link http://api.jqueryui.com/sortable/ JUI Sortable API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/sortable/ JUI Sortable page} for general + * description and demo. + * + * If you are using JavaScript expressions anywhere in the code, please wrap it + * with {@link CJavaScriptExpression} and Yii will use it as code. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiSortable extends CJuiWidget +{ + /** + * @var array list of sortable items (id=>item content). + * Note that the item contents will not be HTML-encoded. + */ + public $items=array(); + /** + * @var string the name of the container element that contains all items. Defaults to 'ul'. + */ + public $tagName='ul'; + /** + * @var string the template that is used to generated every sortable item. + * The token "{content}" in the template will be replaced with the item content, + * while "{id}" be replaced with the item ID. + */ + public $itemTemplate='
            • {content}
            • '; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').sortable({$options});"); + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + foreach($this->items as $id=>$content) + echo strtr($this->itemTemplate,array('{id}'=>$id,'{content}'=>$content))."\n"; + echo CHtml::closeTag($this->tagName); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiTabs.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiTabs.php new file mode 100644 index 0000000..ab4c25a --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiTabs.php @@ -0,0 +1,135 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +Yii::import('zii.widgets.jui.CJuiWidget'); + +/** + * CJuiTabs displays a tabs widget. + * + * CJuiTabs encapsulates the {@link http://jqueryui.com/tabs/ JUI tabs} + * plugin. + * + * To use this widget, you may insert the following code in a view: + *
              + * $this->widget('zii.widgets.jui.CJuiTabs',array(
              + *     'tabs'=>array(
              + *         'StaticTab 1'=>'Content for tab 1',
              + *         'StaticTab 2'=>array('content'=>'Content for tab 2', 'id'=>'tab2'),
              + *         // panel 3 contains the content rendered by a partial view
              + *         'AjaxTab'=>array('ajax'=>$ajaxUrl),
              + *     ),
              + *     // additional javascript options for the tabs plugin
              + *     'options'=>array(
              + *         'collapsible'=>true,
              + *     ),
              + * ));
              + * 
              + * + * By configuring the {@link options} property, you may specify the options + * that need to be passed to the JUI tabs plugin. Please refer to + * the {@link http://api.jqueryui.com/tabs/ JUI Tabs API} documentation + * for possible options (name-value pairs) and + * {@link http://jqueryui.com/tabs/ JUI Tabs page} for general + * description and demo. + * + * @author Sebastian Thierer + * @package zii.widgets.jui + * @since 1.1 + */ +class CJuiTabs extends CJuiWidget +{ + /** + * @var array list of tabs (tab title=>tab content). + * Note that the tab title will not be HTML-encoded. + * The tab content can be either a string or an array. When it is an array, it can + * be in one of the following two formats: + *
              +	 * array('id'=>'myTabID', 'content'=>'tab content')
              +	 * array('id'=>'myTabID', 'ajax'=>URL)
              +	 * 
              + * where the 'id' element is optional. The second format allows the tab content + * to be dynamically fetched from the specified URL via AJAX. The URL can be either + * a string or an array. If an array, it will be normalized into a URL using {@link CHtml::normalizeUrl}. + */ + public $tabs=array(); + /** + * @var string the name of the container element that contains all panels. Defaults to 'div'. + */ + public $tagName='div'; + /** + * @var string the template that is used to generated every panel title. + * The token "{title}" in the template will be replaced with the panel title and + * the token "{url}" will be replaced with "#TabID" or with the url of the ajax request. + */ + public $headerTemplate='
            • {title}
            • '; + /** + * @var string the template that is used to generated every tab content. + * The token "{content}" in the template will be replaced with the panel content + * and the token "{id}" with the tab ID. + */ + public $contentTemplate='
              {content}
              '; + + /** + * Run this widget. + * This method registers necessary javascript and renders the needed HTML code. + */ + public function run() + { + $id=$this->getId(); + if(isset($this->htmlOptions['id'])) + $id=$this->htmlOptions['id']; + else + $this->htmlOptions['id']=$id; + + echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n"; + + $tabsOut=""; + $contentOut=""; + $tabCount=0; + + foreach($this->tabs as $title=>$content) + { + $tabId=(is_array($content) && isset($content['id']))?$content['id']:$id.'_tab_'.$tabCount++; + + if(!is_array($content)) + { + $tabsOut.=strtr($this->headerTemplate,array('{title}'=>$title,'{url}'=>'#'.$tabId,'{id}'=>'#'.$tabId))."\n"; + $contentOut.=strtr($this->contentTemplate,array('{content}'=>$content,'{id}'=>$tabId))."\n"; + } + elseif(isset($content['ajax'])) + { + $tabsOut.=strtr($this->headerTemplate,array('{title}'=>$title,'{url}'=>CHtml::normalizeUrl($content['ajax']),'{id}'=>'#'.$tabId))."\n"; + } + else + { + $tabsOut.=strtr($this->headerTemplate,array('{title}'=>$title,'{url}'=>'#'.$tabId,'{id}'=>$tabId))."\n"; + if(isset($content['content'])) + $contentOut.=strtr($this->contentTemplate,array('{content}'=>$content['content'],'{id}'=>$tabId))."\n"; + } + } + echo "
                \n".$tabsOut."
              \n"; + echo $contentOut; + echo CHtml::closeTag($this->tagName)."\n"; + + $options=CJavaScript::encode($this->options); + Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').tabs($options);"); + } + + /** + * Registers the core script files. + * This method overrides the parent implementation by registering the cookie plugin when cookie option is used. + */ + protected function registerCoreScripts() + { + parent::registerCoreScripts(); + if(isset($this->options['cookie'])) + Yii::app()->getClientScript()->registerCoreScript('cookie'); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiWidget.php b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiWidget.php new file mode 100644 index 0000000..c53186a --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/framework/zii/widgets/jui/CJuiWidget.php @@ -0,0 +1,144 @@ + + * @author Qiang Xue + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * This is the base class for all JUI widget classes. + * + * @author Sebastian Thierer + * @author Qiang Xue + * @package zii.widgets.jui + * @since 1.1 + */ +abstract class CJuiWidget extends CWidget +{ + /** + * @var string the root URL that contains all JUI JavaScript files. + * If this property is not set (default), Yii will publish the JUI package included in the zii release and use + * that to infer the root script URL. You should set this property if you intend to use + * a JUI package whose version is different from the one included in zii. + * Note that under this URL, there must be a file whose name is specified by {@link scriptFile}. + * Do not append any slash character to the URL. + */ + public $scriptUrl; + /** + * @var string the root URL that contains all JUI theme folders. + * If this property is not set (default), Yii will publish the JUI package included in the zii release and use + * that to infer the root theme URL. You should set this property if you intend to use + * a theme that is not found in the JUI package included in zii. + * Note that under this URL, there must be a directory whose name is specified by {@link theme}. + * Do not append any slash character to the URL. + */ + public $themeUrl; + /** + * @var string the JUI theme name. Defaults to 'base'. Make sure that under {@link themeUrl} there + * is a directory whose name is the same as this property value (case-sensitive). + */ + public $theme='base'; + /** + * @var mixed the main JUI JavaScript file. Defaults to 'jquery-ui.min.js'. + * Note the file must exist under the URL specified by {@link scriptUrl}. + * If you need to include multiple script files (e.g. during development, you want to include individual + * plugin script files rather than the minized JUI script file), you may set this property + * as an array of the script file names. + * This property can also be set as false, which means the widget will not include any script file, + * and it is your responsibility to explicitly include it somewhere else. + */ + public $scriptFile='jquery-ui.min.js'; + /** + * @var mixed the theme CSS file name. Defaults to 'jquery-ui.css'. + * Note the file must exist under the URL specified by {@link themeUrl}/{@link theme}. + * If you need to include multiple theme CSS files (e.g. during development, you want to include individual + * plugin CSS files), you may set this property as an array of the CSS file names. + * This property can also be set as false, which means the widget will not include any theme CSS file, + * and it is your responsibility to explicitly include it somewhere else. + */ + public $cssFile='jquery-ui.css'; + /** + * @var array the initial JavaScript options that should be passed to the JUI plugin. + */ + public $options=array(); + /** + * @var array the HTML attributes that should be rendered in the HTML tag representing the JUI widget. + */ + public $htmlOptions=array(); + + /** + * Initializes the widget. + * This method will publish JUI assets if necessary. + * It will also register jquery and JUI JavaScript files and the theme CSS file. + * If you override this method, make sure you call the parent implementation first. + */ + public function init() + { + $this->resolvePackagePath(); + $this->registerCoreScripts(); + parent::init(); + } + + /** + * Determine the JUI package installation path. + * This method will identify the JavaScript root URL and theme root URL. + * If they are not explicitly specified, it will publish the included JUI package + * and use that to resolve the needed paths. + */ + protected function resolvePackagePath() + { + if($this->scriptUrl===null || $this->themeUrl===null) + { + $cs=Yii::app()->getClientScript(); + if($this->scriptUrl===null) + $this->scriptUrl=$cs->getCoreScriptUrl().'/jui/js'; + if($this->themeUrl===null) + $this->themeUrl=$cs->getCoreScriptUrl().'/jui/css'; + } + } + + /** + * Registers the core script files. + * This method registers jquery and JUI JavaScript files and the theme CSS file. + */ + protected function registerCoreScripts() + { + $cs=Yii::app()->getClientScript(); + if(is_string($this->cssFile)) + $cs->registerCssFile($this->themeUrl.'/'.$this->theme.'/'.$this->cssFile); + elseif(is_array($this->cssFile)) + { + foreach($this->cssFile as $cssFile) + $cs->registerCssFile($this->themeUrl.'/'.$this->theme.'/'.$cssFile); + } + + $cs->registerCoreScript('jquery'); + if(is_string($this->scriptFile)) + $this->registerScriptFile($this->scriptFile); + elseif(is_array($this->scriptFile)) + { + foreach($this->scriptFile as $scriptFile) + $this->registerScriptFile($scriptFile); + } + } + + /** + * Registers a JavaScript file under {@link scriptUrl}. + * Note that by default, the script file will be rendered at the end of a page to improve page loading speed. + * @param string $fileName JavaScript file name + * @param integer $position the position of the JavaScript file. Valid values include the following: + *
                + *
              • CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.
              • + *
              • CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.
              • + *
              • CClientScript::POS_END : the script is inserted at the end of the body section.
              • + *
              + */ + protected function registerScriptFile($fileName,$position=CClientScript::POS_END) + { + Yii::app()->getClientScript()->registerScriptFile($this->scriptUrl.'/'.$fileName,$position); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/css/main.css b/src/common/lib/vendor/yiisoft/yii/requirements/css/main.css new file mode 100644 index 0000000..7966881 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/css/main.css @@ -0,0 +1,93 @@ +body +{ + background: white; + font-family:'Lucida Grande',Verdana,Geneva,Lucida,Helvetica,Arial,sans-serif; + font-size:10pt; + font-weight:normal; +} + +#page +{ + width: 800px; + margin: 0 auto; +} + +#header +{ +} + +#content +{ +} + +#footer +{ + color: gray; + font-size:8pt; + border-top:1px solid #aaa; + margin-top:10px; +} + +h1 +{ + color:black; + font-size:1.6em; + font-weight:bold; + margin:0.5em 0pt; +} + +h2 +{ + color:black; + font-size:1.25em; + font-weight:bold; + margin:0.3em 0pt; +} + +h3 +{ + color:black; + font-size:1.1em; + font-weight:bold; + margin:0.2em 0pt; +} + +table.result +{ + background:#E6ECFF none repeat scroll 0% 0%; + border-collapse:collapse; + width:100%; +} + +table.result th +{ + background:#CCD9FF none repeat scroll 0% 0%; + text-align:left; +} + +table.result th, table.result td +{ + border:1px solid #BFCFFF; + padding:0.2em; +} + +td.passed +{ + background-color: #60BF60; + border: 1px solid silver; + padding: 2px; +} + +td.warning +{ + background-color: #FFFFBF; + border: 1px solid silver; + padding: 2px; +} + +td.failed +{ + background-color: #FF8080; + border: 1px solid silver; + padding: 2px; +} diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/index.php new file mode 100644 index 0000000..e3b8dff --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/index.php @@ -0,0 +1,297 @@ + + * @link http://www.yiiframework.com/ + * @copyright 2008-2013 Yii Software LLC + * @license http://www.yiiframework.com/license/ + * @package system + * @since 1.0 + */ +/** + * @var array List of requirements (name, required or not, result, used by, memo) + */ +$requirements=array( + array( + t('yii','PHP version'), + true, + version_compare(PHP_VERSION,"5.1.0",">="), + 'Yii Framework', + t('yii','PHP 5.1.0 or higher is required.')), + array( + t('yii','$_SERVER variable'), + true, + '' === $message=checkServerVar(), + 'Yii Framework', + $message), + array( + t('yii','Reflection extension'), + true, + class_exists('Reflection',false), + 'Yii Framework', + ''), + array( + t('yii','PCRE extension'), + true, + extension_loaded("pcre"), + 'Yii Framework', + ''), + array( + t('yii','SPL extension'), + true, + extension_loaded("SPL"), + 'Yii Framework', + ''), + array( + t('yii','DOM extension'), + false, + class_exists("DOMDocument",false), + 'CHtmlPurifier, CWsdlGenerator', + ''), + array( + t('yii','PDO extension'), + false, + extension_loaded('pdo'), + t('yii','All DB-related classes'), + ''), + array( + t('yii','PDO SQLite extension'), + false, + extension_loaded('pdo_sqlite'), + t('yii','All DB-related classes'), + t('yii','Required for SQLite database.')), + array( + t('yii','PDO MySQL extension'), + false, + extension_loaded('pdo_mysql'), + t('yii','All DB-related classes'), + t('yii','Required for MySQL database.')), + array( + t('yii','PDO PostgreSQL extension'), + false, + extension_loaded('pdo_pgsql'), + t('yii','All DB-related classes'), + t('yii','Required for PostgreSQL database.')), + array( + t('yii','PDO Oracle extension'), + false, + extension_loaded('pdo_oci'), + t('yii','All DB-related classes'), + t('yii','Required for Oracle database.')), + array( + t('yii','PDO MSSQL extension (pdo_mssql)'), + false, + extension_loaded('pdo_mssql'), + t('yii','All DB-related classes'), + t('yii','Required for MSSQL database from MS Windows')), + array( + t('yii','PDO MSSQL extension (pdo_dblib)'), + false, + extension_loaded('pdo_dblib'), + t('yii','All DB-related classes'), + t('yii','Required for MSSQL database from GNU/Linux or other UNIX.')), + array( + t('yii','PDO MSSQL extension (pdo_sqlsrv)'), + false, + extension_loaded('pdo_sqlsrv'), + t('yii','All DB-related classes'), + t('yii','Required for MSSQL database with the driver provided by Microsoft.')), + array( + t('yii','Memcache extension'), + false, + extension_loaded("memcache") || extension_loaded("memcached"), + 'CMemCache', + extension_loaded("memcached") ? t('yii', 'To use memcached set CMemCache::useMemcached to true.') : ''), + array( + t('yii','APC extension'), + false, + extension_loaded("apc"), + 'CApcCache', + ''), + array( + t('yii','Mcrypt extension'), + false, + extension_loaded("mcrypt"), + 'CSecurityManager', + t('yii','Required by encrypt and decrypt methods.')), + array( + t('yii','SOAP extension'), + false, + extension_loaded("soap"), + 'CWebService, CWebServiceAction', + ''), + array( + t('yii','GD extension with
              FreeType support
              or ImageMagick
              extension with
              PNG support'), + false, + '' === $message=checkCaptchaSupport(), + 'CCaptchaAction', + $message), + array( + t('yii','Ctype extension'), + false, + extension_loaded("ctype"), + 'CDateFormatter, CDateTimeParser, CTextHighlighter, CHtmlPurifier', + '' + ), + array( + t('yii','Fileinfo extension'), + false, + extension_loaded("fileinfo"), + 'CFileValidator', + t('yii','Required for MIME-type validation') + ), +); + +function checkServerVar() +{ + $vars=array('HTTP_HOST','SERVER_NAME','SERVER_PORT','SCRIPT_NAME','SCRIPT_FILENAME','PHP_SELF','HTTP_ACCEPT','HTTP_USER_AGENT'); + $missing=array(); + foreach($vars as $var) + { + if(!isset($_SERVER[$var])) + $missing[]=$var; + } + if(!empty($missing)) + return t('yii','$_SERVER does not have {vars}.',array('{vars}'=>implode(', ',$missing))); + + if(realpath($_SERVER["SCRIPT_FILENAME"]) !== realpath(__FILE__)) + return t('yii','$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.'); + + if(!isset($_SERVER["REQUEST_URI"]) && isset($_SERVER["QUERY_STRING"])) + return t('yii','Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.'); + + if(!isset($_SERVER["PATH_INFO"]) && strpos($_SERVER["PHP_SELF"],$_SERVER["SCRIPT_NAME"]) !== 0) + return t('yii','Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.'); + + return ''; +} + +function checkCaptchaSupport() +{ + if(extension_loaded('imagick')) + { + $imagick=new Imagick(); + $imagickFormats=$imagick->queryFormats('PNG'); + } + if(extension_loaded('gd')) + $gdInfo=gd_info(); + if(isset($imagickFormats) && in_array('PNG',$imagickFormats)) + return ''; + elseif(isset($gdInfo)) + { + if($gdInfo['FreeType Support']) + return ''; + return t('yii','GD installed,
              FreeType support not installed'); + } + return t('yii','GD or ImageMagick not installed'); +} + +function getYiiVersion() +{ + $coreFile=dirname(__FILE__).'/../framework/YiiBase.php'; + if(is_file($coreFile)) + { + $contents=file_get_contents($coreFile); + $matches=array(); + if(preg_match('/public static function getVersion.*?return \'(.*?)\'/ms',$contents,$matches) > 0) + return $matches[1]; + } + return ''; +} + +/** + * Returns a localized message according to user preferred language. + * @param string message category + * @param string message to be translated + * @param array parameters to be applied to the translated message + * @return string translated message + */ +function t($category,$message,$params=array()) +{ + static $messages; + + if($messages === null) + { + $messages=array(); + if(($lang=getPreferredLanguage()) !== false) + { + $file=dirname(__FILE__)."/messages/$lang/yii.php"; + if(is_file($file)) + $messages=include($file); + } + } + + if(empty($message)) + return $message; + + if(isset($messages[$message]) && $messages[$message] !== '') + $message=$messages[$message]; + + return $params !== array() ? strtr($message,$params) : $message; +} + +function getPreferredLanguage() +{ + if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n=preg_match_all('/([\w\-]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches)) > 0) + { + $languages=array(); + for($i=0; $i < $n; ++$i) + $languages[$matches[1][$i]]=empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]); + arsort($languages); + foreach($languages as $language=>$pref) + { + $lang=strtolower(str_replace('-','_',$language)); + if (preg_match("/^en\_?/", $lang)) + return false; + if (!is_file($viewFile=dirname(__FILE__)."/views/$lang/index.php")) + $lang=false; + else + break; + } + return $lang; + } + return false; +} + +function getServerInfo() +{ + $info[]=isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : ''; + $info[]='Yii Framework/'.getYiiVersion(); + $info[]=@strftime('%Y-%m-%d %H:%M',time()); + + return implode(' ',$info); +} + +function renderFile($_file_,$_params_=array()) +{ + extract($_params_); + require($_file_); +} + +$result=1; // 1: all pass, 0: fail, -1: pass with warnings + +foreach($requirements as $i=>$requirement) +{ + if($requirement[1] && !$requirement[2]) + $result=0; + else if($result > 0 && !$requirement[1] && !$requirement[2]) + $result=-1; + if($requirement[4] === '') + $requirements[$i][4]=' '; +} + +$lang=getPreferredLanguage(); +$viewFile=dirname(__FILE__)."/views/$lang/index.php"; +if(!is_file($viewFile)) + $viewFile=dirname(__FILE__).'/views/index.php'; + +renderFile($viewFile,array( + 'requirements'=>$requirements, + 'result'=>$result, + 'serverInfo'=>getServerInfo())); + diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/.htaccess b/src/common/lib/vendor/yiisoft/yii/requirements/messages/.htaccess new file mode 100644 index 0000000..e019832 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/ar/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ar/yii.php new file mode 100644 index 0000000..91bb4bf --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ar/yii.php @@ -0,0 +1,42 @@ + '$_SERVER لايحتوي {vars}.', + '$_SERVER variable' => '$_SERVER متغير', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] يجب ان يكون مساوي لمسار Ø§Ù„Ù…Ù„Ù Ø§Ù„Ø§ÙØªØªØ§Ø­ÙŠ Ù„Ù„Ø³ÙƒØ±Ø¨Øª (entry script file).', + 'APC extension' => 'لاحقة APC', + 'All DB-related classes' => 'جميع Ø§Ù„ÙØ¦Ø§Øª ذات العلاقة', + 'DOM extension' => 'DOM لاحقة', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'يجب أن ÙŠØªÙˆÙØ± إما $_SERVER["REQUEST_URI"] أو $_SERVER["QUERY_STRING"].', + 'GD extension' => 'GD لاحقة', + 'Mcrypt extension' => 'Mcrypt لاحقة', + 'Memcache extension' => 'Memcache لاحقة', + 'PCRE extension' => 'PCRE لاحقة', + 'PDO MySQL extension' => 'PDO MySQL لاحقة', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL لاحقة', + 'PDO SQLite extension' => 'PDO SQLite لاحقة', + 'PDO extension' => 'PDO لاحقة', + 'PHP 5.1.0 or higher is required.' => 'يجب وجود إصدارة PHP 5.1.0 أو أعلى.', + 'PHP version' => 'إصدارة PHP', + 'Reflection extension' => 'Reflection لاحقة', + 'SOAP extension' => 'SOAP لاحقة', + 'SPL extension' => 'SPL لاحقة', + 'This is required by encrypt and decrypt methods.' => 'مطلوب من أجل وظائ٠التشÙير ÙˆÙÙƒ التشÙير.', + 'This is required if you are using MySQL database.' => 'مطلوب اذا كنت تستخدم قواعد البيانات MySQL.', + 'This is required if you are using PostgreSQL database.' => 'مطلوب اذا كنت تستخدم قواعد البيانات PostgreSQL.', + 'This is required if you are using SQLite database.' => 'مطلوب اذا كنت تستخدم قواعد البيانات SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'غير قادر على تحديد معلومات مسار العنوان. الرجاء التحقق من أن $_SERVER["PATH_INFO"] (أو $_SERVER["PHP_SELF"] Ùˆ $_SERVER["SCRIPT_NAME"]) تحتوي على القيم الصحيحة.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/bg/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/bg/yii.php new file mode 100644 index 0000000..8a90749 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/bg/yii.php @@ -0,0 +1,31 @@ + '$_SERVER нÑма {vars}.', + '$_SERVER variable' => '$_SERVER променлива', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] трÑбва да бъде ÑÑŠÑ‰Ð¸Ñ ÐºÐ°Ñ‚Ð¾ Ð¿ÑŠÑ‚Ñ Ð´Ð¾ Ð½Ð°Ñ‡Ð°Ð»Ð½Ð¸Ñ Ñкрипт', + 'APC extension' => 'APC добавка', + 'All DB-related classes' => 'Ð’Ñички клаÑове за работа Ñ Ð±Ð°Ð·Ð°Ñ‚Ð° от данни.', + 'DOM extension' => 'DOM разширение', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Или $_SERVER["REQUEST_URI"] или $_SERVER["QUERY_STRING"] трÑбва да ÑъщеÑтвуват', + 'GD extension' => 'GD разширение', + 'Mcrypt extension' => 'Mcrypt разширение', + 'Memcache extension' => 'Memcache разширение', + 'PCRE extension' => 'PCRE разширение', + 'PDO MySQL extension' => 'PDO MySQL разширение', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL разширение', + 'PDO SQLite extension' => 'PDO SQLite разширение', + 'PDO extension' => 'PDO разширение', + 'PHP 5.1.0 or higher is required.' => 'ИзиÑква Ñе минимум PHP 5.1.0.', + 'PHP version' => 'PHP верÑиÑ', + 'Reflection extension' => 'Reflection разширение', + 'SOAP extension' => 'SOAP разширение', + 'SPL extension' => 'SPL разширение', + 'This is required by encrypt and decrypt methods.' => 'Тове Ñе изиÑква от методите за криптиране/декриптиране.', + 'This is required if you are using MySQL database.' => 'Това Ñе изиÑква ако използвате MySQL база от данни.', + 'This is required if you are using PostgreSQL database.' => 'Това Ñе изиÑква ако използвате PostgreSQL база от данни.', + 'This is required if you are using SQLite database.' => 'Това Ñе изиÑква ако използвате SQLite база от данни.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Ðевъзможно е да Ñе определи URL адреÑа. МолÑ, проверете дали $_SERVER["PATH_INFO"] (или $_SERVER["PHP_SELF"] и $_SERVER["SCRIPT_NAME"]) Ñъдържат коректни ÑтойноÑти.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/ca/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ca/yii.php new file mode 100644 index 0000000..3231e1c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ca/yii.php @@ -0,0 +1,41 @@ + 'Home', + 'The button type "{type}" is not supported.' => 'El tipus de botó "{type}" no és suportat.', + 'The property filterSelector should be defined.' => 'La propietat filterSelector hauría d\'estar definida.', + 'The property updateSelector should be defined.' => 'La propietat updateSelector hauría d\'estar definida.', + 'Are you sure you want to delete this item?' => 'De debò que vol eliminar aquest element?', + 'Delete' => 'Eliminar', + 'Displaying {start}-{end} of 1 result.|Displaying {start}-{end} of {count} results.' => 'Desplegant {start}-{end} de 1 resultat.|Desplegant {start}-{end} de {count} resultats.', + 'Either "name" or "value" must be specified for CDataColumn.' => '"name" o "value" s\'han d\'especificar per a CDataColumn.', + 'No results found.' => 'No s\'han trobat resultats.', + 'Not set' => 'No assignat.', + 'Please specify the "attributes" property.' => 'Si us plau, especifiqui la propietat d\'atributs "attributes".', + 'Please specify the "data" property.' => 'Si us plau, especifiqui la propietat "data".', + 'Sort by: ' => 'Ordenat per: ', + 'The "dataProvider" property cannot be empty.' => 'La propietat "dataProvider" no pot ser buida.', + 'The attribute must be specified in the format of "Name:Type:Label", where "Type" and "Label" are optional.' => 'L\'atribut ha d\'especificar-se en el format "Nom:Tipus:Etiqueta", en què "Tipus" i "Etiqueta" són opcionals.', + 'The column must be specified in the format of "Name:Type:Label", where "Type" and "Label" are optional.' => 'La columna ha d\'especificar-se en el format "Nom:Tipus:Etiqueta", en què "Tipus" i "Etiqueta" són opcionals.', + 'The property "itemView" cannot be empty.' => 'La propietat "itemView" no pot ser buida.', + 'Total 1 result.|Total {count} results.' => 'Total de 1 resultat.|Total de {count} resultats.', + 'Update' => 'Actualitzar', + 'View' => 'Mostrar', + '{class} must specify "model" and "attribute" or "name" property values.' => '{class} ha d\'especificar valor/s per a "model" i "atributte" o per a "name".', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/config.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/config.php new file mode 100644 index 0000000..ab977be --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/config.php @@ -0,0 +1,18 @@ +dirname(__FILE__).DIRECTORY_SEPARATOR.'..', + 'messagePath'=>dirname(__FILE__), + 'languages'=>array('zh_cn','zh_tw','de','es','el','sv','he','nl','pt','ru','it','fr','ja','pl','hu','ro','id','vi','bg','uk','cs'), + 'fileTypes'=>array('php'), + 'overwrite'=>true, + 'translator'=>'t', + 'exclude'=>array( + '.gitignore', + '/messages', + '/views', + ), +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/cs/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/cs/yii.php new file mode 100644 index 0000000..cf1243c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/cs/yii.php @@ -0,0 +1,42 @@ + 'Nezbytné pro Å¡ifrovací a deÅ¡ifrovací metody.', + '$_SERVER does not have {vars}.' => '$_SERVER nenalezl {vars}.', + '$_SERVER variable' => '$_SERVER promÄ›nná', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] musí ukazovat na startovací skript.', + 'APC extension' => 'APC rozšíření', + 'All DB-related classes' => 'VÅ¡echny objekty týkající se databází', + 'DOM extension' => 'DOM rozšíření', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] Äi $_SERVER["QUERY_STRING"] musí existovat.', + 'GD extension' => 'GD rozšíření', + 'Mcrypt extension' => 'Mcrypt rozšíření', + 'Memcache extension' => 'Memcache rozšíření', + 'PCRE extension' => 'PCRE rozšíření', + 'PDO MySQL extension' => 'PDO MySQL rozšíření', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL rozšíření', + 'PDO SQLite extension' => 'PDO SQLite rozšíření', + 'PDO extension' => 'PDO rozšíření', + 'PHP 5.1.0 or higher is required.' => 'Je nutná verze PHP 5.1.0 a vyšší.', + 'PHP version' => 'PHP verze', + 'Reflection extension' => 'Reflection rozšíření', + 'SOAP extension' => 'SOAP rozšíření', + 'SPL extension' => 'SPL rozšíření', + 'This is required if you are using MySQL database.' => 'Nutné v případÄ› použití databáze mySQL.', + 'This is required if you are using PostgreSQL database.' => 'Nutné v případÄ› použití databáze PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Nutné v případÄ› použití databáze SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'NepodaÅ™ilo se urÄit URL adresu. UjistÄ›te se, že $_SERVER["PATH_INFO"] (Äi $_SERVER["PHP_SELF"] a $_SERVER["SCRIPT_NAME"]) obsahují správné hodnoty.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/de/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/de/yii.php new file mode 100644 index 0000000..718666b --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/de/yii.php @@ -0,0 +1,49 @@ + 'Ctype Erweiterung', + 'To use memcached set CMemCache::useMemcached to true.' => 'Um memcached verwenden zu können, muss CMemCache::useMemcached auf true gesetzt werden.', + '$_SERVER does not have {vars}.' => '$_SERVER verfügt nicht über {vars}.', + '$_SERVER variable' => '$_SERVER Variable', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] muss auf das Startscript verweisen.', + 'APC extension' => 'APC Erweiterung', + 'All DB-related classes' => 'Alle DB-bezogenen Klassen', + 'DOM extension' => 'DOM Erweiterung', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Entweder $_SERVER["REQUEST_URI"] oder $_SERVER["QUERY_STRING"] müssen exisitieren.', + 'GD extension with
              FreeType support' => 'GD Erweiterung mit
              FreeType-Unterstützung', + 'GD installed
              FreeType support not installed' => 'GD installiert
              FreeType-Unterstützung nicht installiert', + 'GD not installed' => 'GD nicht installiert', + 'Mcrypt extension' => 'Mcyrpt Erweiterung', + 'Memcache extension' => 'Memcache Erweiterung', + 'PCRE extension' => 'PCRE Erweiterung', + 'PDO MySQL extension' => 'PDO MySQL Erweiterung', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL Erweiterung', + 'PDO SQLite extension' => 'PDO SQLite Erweiterung', + 'PDO extension' => 'PDO Erweiterung', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 oder neuer wird benötigt.', + 'PHP version' => 'PHP Version', + 'Reflection extension' => 'Reflection Erweiterung', + 'SOAP extension' => 'SOAP Erweiterung', + 'SPL extension' => 'SPL Erweiterung', + 'This is required by encrypt and decrypt methods.' => 'Wird für Ver- und Entschlüsselungsmethoden benötigt.', + 'This is required if you are using MySQL database.' => 'Wird für die Verwendung einer MySQL Datenbank benötigt.', + 'This is required if you are using PostgreSQL database.' => 'Wird für die Verwendung einer PostgreSQL Datenbank benötigt.', + 'This is required if you are using SQLite database.' => 'Wird für die Verwendung einer SQLite Datenbank benötigt.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Die URL-Pfadinformation kann nicht ermittelt werden. Stellen Sie bitte sicher, dass $_SERVER["PATH_INFO"] (oder $_SERVER["PHP_SELF"] und $_SERVER["SCRIPT_NAME"]) den entsprechenden Wert enthält.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/de_de/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/de_de/yii.php new file mode 100644 index 0000000..d340173 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/de_de/yii.php @@ -0,0 +1,41 @@ + '$_SERVER verfügt nicht über {vars}.', + '$_SERVER variable' => '$_SERVER Variable', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] muss der selbe Eingangsscriptpfad sein.', + 'APC extension' => 'APC Erweiterung', + 'All DB-related classes' => 'Alle DB-bezüglichen Klassen', + 'DOM extension' => 'DOM Erweiterung', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Entweder $_SERVER["REQUEST_URI"] oder $_SERVER["QUERY_STRING"] müssen exisitieren.', + 'GD extension' => 'GD Erweiterung', + 'Mcrypt extension' => 'Mcyrpt Erweiterung', + 'Memcache extension' => 'Memcache Erweiterung', + 'PCRE extension' => 'PCRE Erweiterung', + 'PDO MySQL extension' => 'PDO MySQL Erweiterung', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL Erweiterung', + 'PDO SQLite extension' => 'PDO SQLite Erweiterung', + 'PDO extension' => 'PDO Erweiterung', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 oder Neuer wird benötigt.', + 'PHP version' => 'PHP Version', + 'Reflection extension' => 'Reflection Erweiterung', + 'SOAP extension' => 'SOAP Erweiterung', + 'SPL extension' => 'SPL Erweiterung', + 'This is required if you are using MySQL database.' => 'Dies wird bei Verwendung einer MySQL Datenbank benötigt.', + 'This is required if you are using PostgreSQL database.' => 'Dies wird bei Verwendung einer PostgreSQL Datenbank benötigt.', + 'This is required if you are using SQLite database.' => 'Dies wird bei Verwendung einer SQLite Datenbank benötigt.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Die URL Pfadinformation kann nicht ermittelt werden. Stellen Sie bitte sicher, dass entweder $_SERVER["PATH_INFO"] (oder $_SERVER["PHP_SELF"] und $_SERVER["SCRIPT_NAME"]) mit korrekten Werten gefüllt sind.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/el/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/el/yii.php new file mode 100644 index 0000000..05f542f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/el/yii.php @@ -0,0 +1,57 @@ +FreeType support
              or ImageMagick
              extension with
              PNG support' => 'Επέκταση GD με
              υποστήÏιξη FreeType
              ή ImageMagick
              επέκταση με
              υποστήÏιξη PNG', + 'GD installed,
              FreeType support not installed' => 'Εγκατεστημένη GD,
              η υποστήÏιξη FreeType δεν υπάÏχει', + 'GD or ImageMagick not installed' => 'Το GD ή ImageMagick δεν είναι εγκατεστημένο', + 'PDO MSSQL extension (pdo_sqlsrv)' => 'Επέκταση PDO MSSQL (pdo_sqlsrv)', + 'PDO MSSQL extension (pdo_dblib)' => 'Επέκταση PDO MSSQL (pdo_dblib)', + 'PDO MSSQL extension (pdo_mssql)' => 'Επέκταση PDO MSSQL (pdo_mssql)', + 'PDO Oracle extension' => 'Επέκταση PDO Oracle', + 'This is required if you are using MSSQL database from GNU/Linux or other UNIX.' => 'Απαιτείται αν χÏησιμοποιείτε βάση δεδομένων MSSQL από GNU/Linux ή άλλο UNIX.', + 'This is required if you are using MSSQL database from MS Windows' => 'Απαιτείται αν χÏησιμοποιείτε βάση δεδομένων MSSQL από MS Windows.', + 'This is required if you are using MSSQL database with the driver provided by Microsoft.' => 'Απαιτείται αν χÏησιμοποιείτε βάση δεδομένων MSSQL με οδηγό που παÏέχει η Microsoft.', + 'This is required if you are using Oracle database.' => 'Απαιτείται αν χÏησιμοποιείτε βάση δεδομένων Oracle.', + '$_SERVER does not have {vars}.' => 'Ο πίνακας $_SERVER δεν πεÏιέχει τη(τις) μεταβλητή(-ές) {vars}.', + '$_SERVER variable' => 'Μεταβλητή $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => 'Το $_SERVER["SCRIPT_FILENAME"] Ï€Ïέπει να είναι το ίδιο με το αÏχικό αÏχείο σεναÏίου.', + 'APC extension' => 'Επέκταση APC', + 'All DB-related classes' => 'Όλες οι σχετικές με βάση κλάσεις', + 'Ctype extension' => 'Επέκταση Ctype', + 'DOM extension' => 'Επέκταση DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'ΠÏέπει να υπάÏχει είτε το $_SERVER["REQUEST_URI"] είτε το $_SERVER["QUERY_STRING"].', + 'Mcrypt extension' => 'Επέκταση Mcrypt', + 'Memcache extension' => 'Επέκταση Memcache', + 'PCRE extension' => 'Επέκταση PCRE', + 'PDO MySQL extension' => 'Επέκταση PDO MySQL', + 'PDO PostgreSQL extension' => 'Επέκταση PDO PostgreSQL', + 'PDO SQLite extension' => 'Επέκταση PDO SQLite', + 'PDO extension' => 'Επέκταση PDO', + 'PHP 5.1.0 or higher is required.' => 'Απαιτείται PHP 5.1.0 ή μεγαλÏτεÏης έκδοσης.', + 'PHP version' => 'Έκδοση PHP', + 'Reflection extension' => 'Επέκταση Reflection', + 'SOAP extension' => 'Επέκταση SOAP', + 'SPL extension' => 'Επέκταση SPL', + 'This is required by encrypt and decrypt methods.' => 'Απαιτείται από τις μεθόδους κÏυπτογÏάφησης και αποκÏυπτογÏάφησης.', + 'This is required if you are using MySQL database.' => 'Απαιτείται αν χÏησιμοποιείτε βάση MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Απαιτείται αν χÏησιμοποιείτε βάση PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Απαιτείται αν χÏησιμοποιείτε βάση SQLite.', + 'To use memcached set CMemCache::useMemcached to true.' => 'Για να χÏησιμοποιήσετε memcached, οÏίστε το CMemCache::useMemcached να είναι true.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Δεν ήταν δυνατός ο καθοÏισμός της διαδÏομής URL. ΣιγουÏευτείτε ότι το $_SERVER["PATH_INFO"] (ή $_SERVER["PHP_SELF"] και $_SERVER["SCRIPT_NAME"]) πεÏιέχει τη σωστή τιμή.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/es/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/es/yii.php new file mode 100644 index 0000000..89eb8ce --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/es/yii.php @@ -0,0 +1,42 @@ + '$_SERVER no contiene {vars}', + '$_SERVER variable' => 'variable de $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] debe ser igual a la ruta de entrada del script', + 'APC extension' => 'Extensión APC', + 'All DB-related classes' => 'Todas las clases relacionadas con DB', + 'DOM extension' => 'Extensión DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] o $_SERVER["QUERY_STRING"] deben existir.', + 'GD extension' => 'Extensión GD', + 'Mcrypt extension' => 'Extensión Mcrypt', + 'Memcache extension' => 'Extensión Memcache', + 'PCRE extension' => 'Extensión PCRE', + 'PDO MySQL extension' => 'Extensión PDO MySQL', + 'PDO PostgreSQL extension' => 'Extension PDO PostgreSQL', + 'PDO SQLite extension' => 'Extensión PDO SQLite', + 'PDO extension' => 'Extensión PDO', + 'PHP 5.1.0 or higher is required.' => 'Requiere PHP 5.1.0 o superior', + 'PHP version' => 'Versión PHP', + 'Reflection extension' => 'Extensión Reflection', + 'SOAP extension' => 'Extensión SOAP', + 'SPL extension' => 'Extensión SPL', + 'This is required if you are using MySQL database.' => 'Esto es requerido si se utiliza una base de datos MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Esto es requerido si se utiliza una base de datos PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Esto es requerido si se utiliza una base de datos SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' + => 'No es posible determinar la ruta de información. Por favor asegúrese que $_SERVER["PATH_INFO"] o ($_SERVER["PHP_SELF"] y $_SERVER["SCRIPT_NAME"]) contenga/n un valor correcto.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/fr/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/fr/yii.php new file mode 100644 index 0000000..56daa6a --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/fr/yii.php @@ -0,0 +1,42 @@ + '$_SERVER ne contient pas {vars}.', + '$_SERVER variable' => 'variable $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] doit être égal au chemin du script d\'entrée.', + 'APC extension' => 'extension APC', + 'All DB-related classes' => 'Toutes les classes relatives aux BD.', + 'DOM extension' => 'extension DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Soit $_SERVER["REQUEST_URI"] soit $_SERVER["QUERY_STRING"] doit être défini.', + 'GD extension' => 'extension GD', + 'Mcrypt extension' => 'extension Mcrypt', + 'Memcache extension' => 'extension Memcache', + 'PCRE extension' => 'extension PCRE', + 'PDO MySQL extension' => 'extension PDO MySQL', + 'PDO PostgreSQL extension' => 'extension PDO PostgreSQL', + 'PDO SQLite extension' => 'extension PDO SQLite', + 'PDO extension' => 'extension PDO', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 ou supérieur est requis.', + 'PHP version' => 'Version de PHP', + 'Reflection extension' => 'extension Reflection', + 'SOAP extension' => 'extension SOAP', + 'SPL extension' => 'extension SPL', + 'This is required by encrypt and decrypt methods.' => 'Nécessaire pour les méthodes encrypt et decrypt.', + 'This is required if you are using MySQL database.' => 'Cette extension est requise si vous utilisez une base de donnée MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Cette extension est requise si vous utilisez une base de donnée PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Cette extension est requise si vous utilisez une base de donnée SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Impossible de déterminer les informations sur le chemin dans l\'URL. Vérifier que $_SERVER["PATH_INFO"] (ou $_SERVER["PHP_SELF"] et $_SERVER["SCRIPT_NAME"]) ont la bonne valeur', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/he/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/he/yii.php new file mode 100644 index 0000000..b4ff98d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/he/yii.php @@ -0,0 +1,41 @@ + '$_SERVER ×œ× ×ž×›×™×œ {vars}.', + '$_SERVER variable' => '$_SERVER משתנה', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] חייב להיות ×–×”×” לנתיב ×”×ž×œ× ×œ×§×•×‘×¥ הר×שי.', + 'APC extension' => 'תוסף APC', + 'All DB-related classes' => 'כל מחלקות מסדי הנתוני×', + 'DOM extension' => 'תוסף DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] ×ו $_SERVER["QUERY_STRING"] חייב להיות ×§×™×™×.', + 'GD extension' => 'תוסף GD', + 'Mcrypt extension' => 'תוסף Mcrypt', + 'Memcache extension' => 'תוסף Memcache', + 'PCRE extension' => 'תוסף PCRE', + 'PDO MySQL extension' => 'תוסף PDO MySQL', + 'PDO PostgreSQL extension' => 'תוסף PDO PostgreSQL', + 'PDO SQLite extension' => 'תוסף PDO SQLite', + 'PDO extension' => 'תוסף PDO', + 'PHP 5.1.0 or higher is required.' => 'PHP ×‘×’×¨×¡× 5.1.0 ×ו יותר דרוש.', + 'PHP version' => 'גרס×ת PHP', + 'Reflection extension' => 'תוסף Reflection', + 'SOAP extension' => 'תוסף SOAP', + 'SPL extension' => 'תוסף SPL', + 'This is required if you are using MySQL database.' => 'תוסף ×–×” נחוץ ×× ×”×™× ×š מתכוון להשתמש במסד × ×ª×•× ×™× ×ž×¡×•×’ MYSQL.', + 'This is required if you are using PostgreSQL database.' => 'תוסף ×–×” נחוץ ×× ×”×™× ×š מתכוון להשתמש במסד × ×ª×•× ×™× ×ž×¡×•×’ PostgreSQL.', + 'This is required if you are using SQLite database.' => 'תוסף ×–×” נחוץ ×× ×”×™× ×š מתכוון להשתמש במסד × ×ª×•× ×™× ×ž×¡×•×’ SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => '×œ× × ×™×ª×Ÿ לזהות ×ת נתיבי הקישור. ×× × ×•×•×“× ×©×”×¢×¨×š $_SERVER["PATH_INFO"] (×ו $_SERVER["PHP_SELF"] ו $_SERVER["SCRIPT_NAME"]) ×ž×›×™×œ×™× ×¢×¨×›×™× ×ž×ª×ימי×.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/hu/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/hu/yii.php new file mode 100644 index 0000000..7fef6b2 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/hu/yii.php @@ -0,0 +1,42 @@ + '', + '$_SERVER variable' => '', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '', + 'APC extension' => '', + 'All DB-related classes' => '', + 'DOM extension' => '', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '', + 'GD extension' => '', + 'Mcrypt extension' => '', + 'Memcache extension' => '', + 'PCRE extension' => '', + 'PDO MySQL extension' => '', + 'PDO PostgreSQL extension' => '', + 'PDO SQLite extension' => '', + 'PDO extension' => '', + 'PHP 5.1.0 or higher is required.' => '', + 'PHP version' => '', + 'Reflection extension' => '', + 'SOAP extension' => '', + 'SPL extension' => '', + 'This is required by encrypt and decrypt methods.' => '', + 'This is required if you are using MySQL database.' => '', + 'This is required if you are using PostgreSQL database.' => '', + 'This is required if you are using SQLite database.' => '', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => '', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/id/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/id/yii.php new file mode 100644 index 0000000..2fe1527 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/id/yii.php @@ -0,0 +1,49 @@ + 'Extension Ctype', + '$_SERVER does not have {vars}.' => '$_SERVER tidak memiliki {vars}.', + '$_SERVER variable' => 'Variabel $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] harus sama dengan alur file skrip entri', + 'APC extension' => 'Extension APC', + 'All DB-related classes' => 'Semua kelas berhubungan DB ', + 'DOM extension' => 'Extension DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Salah satu dari $_SERVER["REQUEST_URI"] atau $_SERVER["QUERY_STRING"] harus ada.', + 'GD extension with
              FreeType support' => 'Dukungan Extension GD dengan
              FreeType', + 'GD installed
              FreeType support not installed' => 'GD terinstalasi
              Dukungan FreeType tidak terinstalasi', + 'GD not installed' => 'GD tidak terinstalasi', + 'Mcrypt extension' => 'Extension Mcrypt', + 'Memcache extension' => 'Extension Memcache', + 'PCRE extension' => 'Extension PCRE', + 'PDO MySQL extension' => 'Extension PDO MySQL', + 'PDO PostgreSQL extension' => 'Extension PDO PostgreSQL', + 'PDO SQLite extension' => 'Extension PDO SQLite', + 'PDO extension' => 'Extension PDO', + 'PHP 5.1.0 or higher is required.' => 'Diperlukan PHP 5.1.0 atau lebih tinggi.', + 'PHP version' => 'Versi PHP', + 'Reflection extension' => 'Extension Reflection', + 'SOAP extension' => 'Extension SOAP', + 'SPL extension' => 'Extension SPL', + 'This is required by encrypt and decrypt methods.' => 'Ini diperlukan oleh method enkripsi dan dekripsi', + 'This is required if you are using MySQL database.' => 'Ini diperlukan apabila anda menggunakan database MySQL', + 'This is required if you are using PostgreSQL database.' => 'Ini diperlukan apabila anda menggunakan database PostgreSQL', + 'This is required if you are using SQLite database.' => 'Ini diperlukan apabila anda menggunakan database SQLite', + 'To use memcached set CMemCache::useMemcached to true.' => 'Untuk menggunakan memcached set CMemCache::useMemcached menjadi true.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Tidak dapat menentukan info alur URL. Harap memastikan $_SERVER["PATH_INFO"] (atau $_SERVER["PHP_SELF"] dan $_SERVER"SCRIPT_NAME"]) berisi nilai yang benar.', +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/it/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/it/yii.php new file mode 100644 index 0000000..bf738e4 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/it/yii.php @@ -0,0 +1,41 @@ + '$_SERVER non contiene {vars}.', + '$_SERVER variable' => 'variabile $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] deve essere identico al path del file di entrata.', + 'APC extension' => 'Estensione APC', + 'All DB-related classes' => 'Tutte le classi legate al DB', + 'DOM extension' => 'Estensione DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Uno tra $_SERVER["REQUEST_URI"] o $_SERVER["QUERY_STRING"] deve esistere', + 'GD extension' => 'Estensione GD', + 'Mcrypt extension' => 'Estensione Mcrypt', + 'Memcache extension' => 'Estensione Memcache', + 'PCRE extension' => 'Estensione PCRE', + 'PDO MySQL extension' => 'Estensione PDO MySQL', + 'PDO PostgreSQL extension' => 'Estensione PDO PostgreSQL', + 'PDO SQLite extension' => 'Estensione PDO SQLite', + 'PDO extension' => 'Estensione PDO', + 'PHP 5.1.0 or higher is required.' => 'È richiesto PHP 5.1.0 o superiore', + 'PHP version' => 'Versione PHP', + 'Reflection extension' => 'Estensione Reflection', + 'SOAP extension' => 'Estensione SOAP', + 'SPL extension' => 'Estensione SPL', + 'This is required if you are using MySQL database.' => 'Necessario se si utilizza il database MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Necessario se si utilizza il database PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Necessario se si utilizza il database SQLite .', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Impossibile determinare il path dell\'URL. Assicurarsi che $_SERVER["PATH_INFO"] (o $_SERVER["PHP_SELF"] e $_SERVER["SCRIPT_NAME"]) contengano valori adeguati.', +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/ja/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ja/yii.php new file mode 100644 index 0000000..6d746bc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ja/yii.php @@ -0,0 +1,59 @@ + '$_SERVER ã« {vars} ãŒå­˜åœ¨ã—ã¾ã›ã‚“。', + '$_SERVER variable' => '$_SERVER 変数', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] ã¯ã€ã‚¨ãƒ³ãƒˆãƒªã‚¹ã‚¯ãƒªãƒ—トã®ãƒ‘スã¨åŒã˜ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。', + 'APC extension' => 'APC æ‹¡å¼µ', + 'All DB-related classes' => 'å…¨ã¦ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹é–¢é€£ã‚¯ãƒ©ã‚¹', + 'Ctype extension' => 'Ctype æ‹¡å¼µ', + 'DOM extension' => 'DOM æ‹¡å¼µ', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] ã‹ $_SERVER["QUERY_STRING"] ã®ã©ã¡ã‚‰ã‹ãŒå­˜åœ¨ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。', + 'Fileinfo extension' => 'Fileinfo æ‹¡å¼µ', + 'GD extension with
              FreeType support
              or ImageMagick
              extension with
              PNG support' => 'GD æ‹¡å¼µ
              (+ FreeType サãƒãƒ¼ãƒˆ)
              ã¾ãŸã¯
              ImageMagick æ‹¡å¼µ
              (+ PNG サãƒãƒ¼ãƒˆ)', + 'GD installed,
              FreeType support not installed' => 'GD インストール済ã¿
              FreeType サãƒãƒ¼ãƒˆ 未インストール', + 'GD or ImageMagick not installed' => 'GD ã‚‚ ImageMagick も未インストール', + 'Mcrypt extension' => 'Mcrypt æ‹¡å¼µ', + 'Memcache extension' => 'Memcache æ‹¡å¼µ', + 'PCRE extension' => 'PCRE æ‹¡å¼µ', + 'PDO MSSQL extension (pdo_sqlsrv)' => 'PDO MSSQL æ‹¡å¼µ (pdo_sqlsrv)', + 'PDO MSSQL extension (pdo_dblib)' => 'PDO MSSQL æ‹¡å¼µ (pdo_dblib)', + 'PDO MSSQL extension (pdo_mssql)' => 'PDO MSSQL æ‹¡å¼µ (pdo_mssql)', + 'PDO MySQL extension' => 'PDO MySQL æ‹¡å¼µ', + 'PDO Oracle extension' => 'PDO Oracle æ‹¡å¼µ', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL æ‹¡å¼µ', + 'PDO SQLite extension' => 'PDO SQLite æ‹¡å¼µ', + 'PDO extension' => 'PDO æ‹¡å¼µ', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 以上ãŒå¿…è¦ã§ã™ã€‚', + 'PHP version' => 'PHP ãƒãƒ¼ã‚¸ãƒ§ãƒ³', + 'Reflection extension' => 'Reflection æ‹¡å¼µ', + 'Required by encrypt and decrypt methods.' => 'æš—å·åŒ–ã¨å¾©å·ã®ãƒ¡ã‚½ãƒƒãƒ‰ã«å¿…è¦ã€‚', + 'Required for MIME-type validation' => 'MIME-type ãƒãƒªãƒ‡ãƒ¼ã‚·ãƒ§ãƒ³ã«å¿…è¦ã€‚', + 'Required for MSSQL database from GNU/Linux or other UNIX.' => 'GNU/Linux ãã®ä»–ã® UNIX ã§ MSSQL データベース を使用ã™ã‚‹å ´åˆã«å¿…è¦ã€‚', + 'Required for MSSQL database from MS Windows' => 'MS Windows ã§ MSSQL データベースを使用ã™ã‚‹å ´åˆã«å¿…è¦ã€‚', + 'Required for MSSQL database with the driver provided by Microsoft.' => 'Microsoft ã«ã‚ˆã£ã¦æä¾›ã•れã¦ã„るドライãƒã§ MSSQL データベースを使用ã™ã‚‹å ´åˆã«å¿…è¦ã€‚', + 'Required for MySQL database.' => 'MySQL データベースを使用ã™ã‚‹å ´åˆã«å¿…è¦ã€‚', + 'Required for Oracle database.' => 'Oracle データベースを使用ã™ã‚‹å ´åˆã«å¿…è¦ã€‚', + 'Required for PostgreSQL database.' => 'PostgreSQL データベースを使用ã™ã‚‹å ´åˆã«å¿…è¦ã€‚', + 'Required for SQLite database.' => 'SQLite データベースを使用ã™ã‚‹å ´åˆã«å¿…è¦ã€‚', + 'SOAP extension' => 'SOAP æ‹¡å¼µ', + 'SPL extension' => 'SPL æ‹¡å¼µ', + 'To use memcached set CMemCache::useMemcached to true.' => 'memcached を使用ã™ã‚‹ãŸã‚ã«ã¯ CMemCache::useMemcached ã‚’ true ã«è¨­å®šã—ã¦ä¸‹ã•ã„。', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'URL パス情報を決定ã§ãã¾ã›ã‚“。$_SERVER["PATH_INFO"] (ã‚‚ã—ã㯠$_SERVER["PHP_SELF"] 㨠$_SERVER["SCRIPT_NAME"]) ãŒæ­£ã—ã„値ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„。', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/nl/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/nl/yii.php new file mode 100644 index 0000000..74e47e4 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/nl/yii.php @@ -0,0 +1,41 @@ + '$_SERVER heeft geen {vars}.', + '$_SERVER variable' => '$_SERVER variabele', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] moet hetzelfde zijn als het bestandspad van het startscript.', + 'APC extension' => 'APC extensie', + 'All DB-related classes' => 'Alle DB-gerelateerde classes', + 'DOM extension' => 'DOM extensie', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Of $_SERVER["REQUEST_URI"] of $_SERVER["QUERY_STRING"] moet gedefinieerd zijn.', + 'GD extension' => 'GD extensie', + 'Mcrypt extension' => 'Mcrypt extensie', + 'Memcache extension' => 'Memcache extensie', + 'PCRE extension' => 'PCRE extensie', + 'PDO MySQL extension' => 'PDO MySQL extensie', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL extensie', + 'PDO SQLite extension' => 'PDO SQLite extensie', + 'PDO extension' => 'PDO extensie', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 of hoger is vereist.', + 'PHP version' => 'PHP versie', + 'Reflection extension' => 'Reflection extensie', + 'SOAP extension' => 'SOAP extensie', + 'SPL extension' => 'SPL extensie', + 'This is required if you are using MySQL database.' => 'Dit is vereist als een MySQL database wordt gebruikt.', + 'This is required if you are using PostgreSQL database.' => 'Dit is vereist als een PostgreSQL database wordt gebruikt.', + 'This is required if you are using SQLite database.' => 'Dit is vereist als een SQLite database wordt gebruikt.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Niet in staat om informatie over het URL pad te verkrijgen. Zorg er a.u.b. voor dat $_SERVER["PATH_INFO"] (of $_SERVER["PHP_SELF"] en $_SERVER["SCRIPT_NAME"]) een juiste waarde bevatten.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/no/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/no/yii.php new file mode 100644 index 0000000..c16975d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/no/yii.php @@ -0,0 +1,42 @@ + '$_SERVER inneholder ikke {vars}', + '$_SERVER variable' => '$_SERVER variabel', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] mÃ¥ være lik filbanen til startscriptet', + 'APC extension' => 'APC-tillegg', + 'All DB-related classes' => 'Alle DB-relaterte klasser', + 'DOM extension' => 'DOM-extension', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '', + 'GD extension' => 'GD-extension', + 'Mcrypt extension' => 'Mcrypt-extension', + 'Memcache extension' => 'Memcache-extension', + 'PCRE extension' => 'PCRE-extension', + 'PDO MySQL extension' => 'PDO MYSQL-extension', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL-extension', + 'PDO SQLite extension' => 'PDO SQLite-extension', + 'PDO extension' => 'PDO-extension', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 eller nyere er pÃ¥krevet', + 'PHP version' => 'PHP-versjon', + 'Reflection extension' => 'Reflection-extension', + 'SOAP extension' => 'SOAP-extension', + 'SPL extension' => 'SPL-extension', + 'This is required by encrypt and decrypt methods.' => 'Dette kreves av kryptering- og dekrypteringsmetodene.', + 'This is required if you are using MySQL database.' => 'Dette kreves hvis du bruker en MySQL database.', + 'This is required if you are using PostgreSQL database.' => 'Dette kreves hvis du bruker en PostgreSQL database.', + 'This is required if you are using SQLite database.' => 'Dette kreves hvis du bruker en SQLite database.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Kunne ikke finne path info. Vennligst sjekk at $_SERVER["PATH_INFO"] (eller $_SERVER["PHP_SELF"] og $_SERVER["SCRIPT_NAME"]) inneholder riktige verdier.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/pl/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/pl/yii.php new file mode 100644 index 0000000..bce5637 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/pl/yii.php @@ -0,0 +1,44 @@ +FreeType support' => 'Rozszerzenie GD
              ze wsparciem dla FreeType', + 'GD installed
              FreeType support not installed' => 'Rozszerzenie GD jest zainstalowane
              ale bez wsparcia FreeType', + 'GD not installed' => 'Nie zainstalowano GD', + '$_SERVER does not have {vars}.' => '$_SERVER nie posiada zmiennej(nych) {vars}', + '$_SERVER variable' => 'zmienna $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] musi być taki sam jak ścieżka pliku skryptu wejściowego.', + 'APC extension' => 'rozszerzenie APC', + 'All DB-related classes' => 'Wszystkie klasy bazodanowe', + 'DOM extension' => 'rozszerzenie DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Zarówno $_SERVER["REQUEST_URI"] jak i $_SERVER["QUERY_STRING"] muszą istnieć.', + 'Mcrypt extension' => 'rozszerzenie Mcrypt', + 'Memcache extension' => 'rozszerzenie Memcache', + 'PCRE extension' => 'rozszerzenie PCRE', + 'PDO MySQL extension' => 'rozszerzenie PDO MySQL', + 'PDO PostgreSQL extension' => 'rozszerzenie PDO PostgreSQL ', + 'PDO SQLite extension' => 'rozszerzenie PDO SQLite ', + 'PDO extension' => 'rozszerzenie PDO', + 'PHP 5.1.0 or higher is required.' => 'Wymagane jest PHP w wersji 5.1.0 lub wyższej', + 'PHP version' => 'wersja PHP', + 'Reflection extension' => 'rozszerzenie Reflection', + 'SOAP extension' => 'rozszerzenie SOAP', + 'SPL extension' => 'rozszerzenie SPL', + 'This is required by encrypt and decrypt methods.' => 'Wymagane przez metody szyfrujące i deszyfrujące.', + 'This is required if you are using MySQL database.' => 'Wymagane jeśli używasz bazy danych MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Wymagane jeśli używasz bazy danych PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Wymagane jeśli używasz bazy danych SQLite', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Nie można określić ścieżki URL. Upewnij się, że $_SERVER["PATH_INFO"] (lub $_SERVER["PHP_SELF"] oraz $_SERVER["SCRIPT_NAME"]) zawierają odpowiednie wartości.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/pt/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/pt/yii.php new file mode 100644 index 0000000..d2abebc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/pt/yii.php @@ -0,0 +1,42 @@ + 'É necessário aos métodos encrypt e decrypt.', + '$_SERVER does not have {vars}.' => '$_SERVER não possui {vars}.', + '$_SERVER variable' => 'variável $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] precisa ser o mesmo que o arquivo de script de entrada.', + 'APC extension' => 'extensão APC', + 'All DB-related classes' => 'Todas as classes relacionadas ao banco de dados', + 'DOM extension' => 'extensão DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] ou $_SERVER["QUERY_STRING"] é obrigatório.', + 'GD extension' => 'extensão GD', + 'Mcrypt extension' => 'extensão Mcrypt', + 'Memcache extension' => 'extensão Memcache', + 'PCRE extension' => 'extensão PCRE', + 'PDO MySQL extension' => 'extensão PDO_MySQL', + 'PDO PostgreSQL extension' => 'extensão PDO_PostgreSQL', + 'PDO SQLite extension' => 'extensão PDO_SQLite', + 'PDO extension' => 'extensão PDO', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 ou mais recente é necessário.', + 'PHP version' => 'versão PHP', + 'Reflection extension' => 'extensão Reflection', + 'SOAP extension' => 'extensão SOAP', + 'SPL extension' => 'extensão SPL', + 'This is required if you are using MySQL database.' => 'Este item é obrigatório se você estiver utilizando MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Este item é obrigatório se você estiver utilizando PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Este item é obrigatório se você estiver utilizando SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Não foi possível determinar o caminho da URL. Verifique se $_SERVER["PATH_INFO"] (ou $_SERVER["PHP_SELF"] e $_SERVER["SCRIPT_NAME"]) contem os valores corretos.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/pt_br/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/pt_br/yii.php new file mode 100644 index 0000000..5ad7ae4 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/pt_br/yii.php @@ -0,0 +1,50 @@ + 'extensão Ctype', + 'GD extension with
              FreeType support' => 'extensão GD com
              suporte a FreeType', + 'GD installed
              FreeType support not installed' => 'GD instalada
              suporte a FreeType não instalado', + 'GD not installed' => 'GD não instalada', + 'To use memcached set CMemCache::useMemcached to true.' => 'Para usar memcached configure CMemCache::useMemcached como true.', + 'GD extension' => '@@extensão GD@@', + '$_SERVER does not have {vars}.' => '$_SERVER não possui {vars}.', + '$_SERVER variable' => 'variável $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] precisa ser o mesmo que o arquivo de script de entrada.', + 'APC extension' => 'extensão APC', + 'All DB-related classes' => 'Todas as classes relacionadas ao banco de dados', + 'DOM extension' => 'extensão DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] ou $_SERVER["QUERY_STRING"] é obrigatório.', + 'Mcrypt extension' => 'extensão Mcrypt', + 'Memcache extension' => 'extensão Memcache', + 'PCRE extension' => 'extensão PCRE', + 'PDO MySQL extension' => 'extensão PDO_MySQL', + 'PDO PostgreSQL extension' => 'extensão PDO_PostgreSQL', + 'PDO SQLite extension' => 'extensão PDO_SQLite', + 'PDO extension' => 'extensão PDO', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 ou mais recente é necessário.', + 'PHP version' => 'versão PHP', + 'Reflection extension' => 'extensão Reflection', + 'SOAP extension' => 'extensão SOAP', + 'SPL extension' => 'extensão SPL', + 'This is required by encrypt and decrypt methods.' => 'Este item é necessário aos métodos encrypt e decrypt.', + 'This is required if you are using MySQL database.' => 'Este item é obrigatório se você estiver utilizando MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Este item é obrigatório se você estiver utilizando PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Este item é obrigatório se você estiver utilizando SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Não foi possível determinar o caminho da URL. Verifique se $_SERVER["PATH_INFO"] (ou $_SERVER["PHP_SELF"] e $_SERVER["SCRIPT_NAME"]) contem os valores corretos.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/ro/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ro/yii.php new file mode 100644 index 0000000..0d81f7d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ro/yii.php @@ -0,0 +1,42 @@ + '$_SERVER nu are {vars}.', + '$_SERVER variable' => 'Variabila $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] trebuie sa fie aceeasi cu calea fisierului scriptului de intrare.', + 'APC extension' => 'Extensia APC', + 'All DB-related classes' => 'Toate clasele de legatura cu bazele de date', + 'DOM extension' => 'Extensia DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Trebuie sa existe fie $_SERVER["REQUEST_URI"] fie $_SERVER["QUERY_STRING"].', + 'GD extension' => 'Extensia GD', + 'Mcrypt extension' => 'Extensia Mcrypt', + 'Memcache extension' => 'Extensia Memcache', + 'PCRE extension' => 'Extensia PCRE', + 'PDO MySQL extension' => 'Extensia PDO MySQL', + 'PDO PostgreSQL extension' => 'Extensia PDO PostgreSQL', + 'PDO SQLite extension' => 'Extensia PDO SQLite', + 'PDO extension' => 'Extensia PDO', + 'PHP 5.1.0 or higher is required.' => 'Este obligatoriu PHP 5.1.0 sau mai nou.', + 'PHP version' => 'Versiunea PHP', + 'Reflection extension' => 'Extensia Reflection', + 'SOAP extension' => 'Extensia SOAP', + 'SPL extension' => 'Extensia SPL', + 'This is required by encrypt and decrypt methods.' => 'Obligatoriu pentru metodele encrypt si decrypt.', + 'This is required if you are using MySQL database.' => 'Obligatoriu daca folositi baza de date MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Obligatoriu daca folositi baza de date PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Obligatoriu daca folositi baza de date SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Nu se pot determina informatiile despre calea URL. Asigurati-va ca $_SERVER["PATH_INFO"] (sau $_SERVER["PHP_SELF"] si $_SERVER["SCRIPT_NAME"]) contine valoarea potrivita.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/ru/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ru/yii.php new file mode 100644 index 0000000..db3201e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ru/yii.php @@ -0,0 +1,59 @@ + 'РаÑширение Fileinfo.', + 'Required by encrypt and decrypt methods.' => 'ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ методов ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ дешифрации.', + 'Required for MIME-type validation' => 'ТребуетÑÑ Ð´Ð»Ñ Ð²Ð°Ð»Ð¸Ð´Ð°Ñ†Ð¸Ð¸ MIME-типов.', + 'Required for MSSQL database from GNU/Linux or other UNIX.' => 'ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð‘Ð” MSSQL при иÑпользовании из GNU/Linux или UNIX.', + 'Required for MSSQL database from MS Windows' => 'ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð‘Ð” MSSQL при иÑпользовании из MS Windows.', + 'Required for MSSQL database with the driver provided by Microsoft.' => 'ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð‘Ð” MSSQL при иÑпользовании драйвера от Microsoft.', + 'Required for MySQL database.' => 'ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð‘Ð” MySQL.', + 'Required for Oracle database.' => 'ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð‘Ð” Oracle.', + 'Required for PostgreSQL database.' => 'ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð‘Ð” PostgreSQL.', + 'Required for SQLite database.' => 'ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð‘Ð” SQLite.', + '$_SERVER does not have {vars}.' => 'ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ $_SERVER не Ñодержит {vars}.', + '$_SERVER variable' => 'ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ $_SERVER.', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => 'ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ $_SERVER["SCRIPT_FILENAME"] должна ÑоответÑтвовать пути к файлу входного Ñкрипта.', + 'APC extension' => 'РаÑширение APC', + 'All DB-related classes' => 'Ð’Ñе DB-клаÑÑÑ‹', + 'Ctype extension' => 'РаÑширение Ctype', + 'DOM extension' => 'РаÑширение DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Должна ÑущеÑтвовать Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одна из Ñерверных переменных: $_SERVER["REQUEST_URI"] или $_SERVER["QUERY_STRING"].', + 'GD extension with
              FreeType support
              or ImageMagick
              extension with
              PNG support' => 'РаÑширение GD
              Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ FreeType
              или ImageMagick
              Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ PNG', + 'GD installed,
              FreeType support not installed' => 'РаÑширение GD уÑтановлено
              без поддержки FreeType', + 'GD or ImageMagick not installed' => 'РаÑшиение GD или ImageMagick не уÑтановлены', + 'Mcrypt extension' => 'РаÑширение Mcrypt', + 'Memcache extension' => 'РаÑширение Memcache', + 'PCRE extension' => 'РаÑширение PCRE', + 'PDO MSSQL extension (pdo_sqlsrv)' => 'РаÑширение PDO MSSQL (pdo_sqlsrv)', + 'PDO MSSQL extension (pdo_dblib)' => 'РаÑширение PDO MSSQL (pdo_dblib)', + 'PDO MSSQL extension (pdo_mssql)' => 'РаÑширение PDO MSSQL (pdo_mssql)', + 'PDO MySQL extension' => 'РаÑширение PDO MySQL', + 'PDO Oracle extension' => 'РаÑширение PDO Oracle', + 'PDO PostgreSQL extension' => 'РаÑширение PDO PostgreSQL', + 'PDO SQLite extension' => 'РаÑширение PDO SQLite', + 'PDO extension' => 'РаÑширение PDO', + 'PHP 5.1.0 or higher is required.' => 'Ðеобходима верÑÐ¸Ñ Ð ÐР 5.1.0 и выше.', + 'PHP version' => 'ВерÑÐ¸Ñ Ð ÐР', + 'Reflection extension' => 'РаÑширение', + 'SOAP extension' => 'РаÑширение SOAP', + 'SPL extension' => 'РаÑширение SPL', + 'To use memcached set CMemCache::useMemcached to true.' => 'Чтобы иÑпользовать memcached уÑтановите значение ÑвойÑтва CMemCache::useMemcached равным true.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Ðе удалоÑÑŒ получить информацию о пути. ПожалуйÑта, проверьте, ÑодержитÑÑ Ð»Ð¸ корректное значение в переменной $_SERVER["PATH_INFO"] (или $_SERVER["PHP_SELF"] и $_SERVER["SCRIPT_NAME"]).', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/sk/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/sk/yii.php new file mode 100644 index 0000000..ec299a2 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/sk/yii.php @@ -0,0 +1,42 @@ + 'Nevyhnutné pre kryptovacie a dekryptovacie metódy.', + '$_SERVER does not have {vars}.' => '$_SERVER nenaÅ¡iel {vars}.', + '$_SERVER variable' => '$_SERVER premenná', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] musí ukazovaÅ¥ na Å¡tartovací skript.', + 'APC extension' => 'APC rozšírenie', + 'All DB-related classes' => 'VÅ¡etky objekty vzÅ¥ahujúce sa k databáze', + 'DOM extension' => 'DOM rozšírenie', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] alebo $_SERVER["QUERY_STRING"] musia existovaÅ¥.', + 'GD extension' => 'GD rozšírenie', + 'Mcrypt extension' => 'Mcrypt rozšírenie', + 'Memcache extension' => 'Memcache rozšírenie', + 'PCRE extension' => 'PCRE rozšírenie', + 'PDO MySQL extension' => 'PDO MySQL rozšírenie', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL rozšírenie', + 'PDO SQLite extension' => 'PDO SQLite rozšírenie', + 'PDO extension' => 'PDO rozšírenie', + 'PHP 5.1.0 or higher is required.' => 'Je potrebná verzia PHP 5.1.0 alebo vyššia.', + 'PHP version' => 'PHP verzia', + 'Reflection extension' => 'Reflection rozšírenie', + 'SOAP extension' => 'SOAP rozšírenie', + 'SPL extension' => 'SPL rozšírenie', + 'This is required if you are using MySQL database.' => 'Potrebné v prípade využitia databázy mySQL.', + 'This is required if you are using PostgreSQL database.' => 'Potrebné v prípade využitia databázy PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Potrebné v prípade využitia databázy SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Nepodarilo sa zistiÅ¥ informácie o URL linke. UbezúpeÄte sa, že $_SERVER["PATH_INFO"] (alebo $_SERVER["PHP_SELF"] a $_SERVER["SCRIPT_NAME"]) obsahuje správne hodnoty.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/sv/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/sv/yii.php new file mode 100644 index 0000000..df6eff1 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/sv/yii.php @@ -0,0 +1,49 @@ + 'Ctype-tillägg', + '$_SERVER does not have {vars}.' => '$_SERVER innehÃ¥ller inte {vars}.', + '$_SERVER variable' => '$_SERVER-variabel', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] mÃ¥ste vara samma som startskriptets namn och sökväg.', + 'APC extension' => 'APC-tillägg', + 'All DB-related classes' => 'Alla DB-relaterade klasser', + 'DOM extension' => 'DOM-tillägg', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Antingen $_SERVER["REQUEST_URI"] eller $_SERVER["QUERY_STRING"] mÃ¥ste finnas.', + 'GD extension with
              FreeType support' => 'GD-tillägg med
              FreeType-stöd', + 'GD installed
              FreeType support not installed' => 'GD installerad
              FreeType-stöd ej installerat', + 'GD not installed' => 'GD ej installerat', + 'Mcrypt extension' => 'Mcrypt-tillägg', + 'Memcache extension' => 'Memcache-tillägg', + 'PCRE extension' => 'PCRE-tillägg', + 'PDO MySQL extension' => 'PDO MySQL-tillägg', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL-tillägg', + 'PDO SQLite extension' => 'PDO SQLite-tillägg', + 'PDO extension' => 'PDO-tillägg', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 eller senare krävs', + 'PHP version' => 'PHP-version', + 'Reflection extension' => 'Reflection-tillägg', + 'SOAP extension' => 'SOAP-tillägg', + 'SPL extension' => 'SPL-tillägg', + 'This is required by encrypt and decrypt methods.' => 'Detta krävs av krypterings- och dekrypteringsmetoderna', + 'This is required if you are using MySQL database.' => 'Detta krävs om MySQL-databas används.', + 'This is required if you are using PostgreSQL database.' => 'Detta krävs om PostgresSQL-databas används.', + 'This is required if you are using SQLite database.' => 'Detta krävs om SQLite-databas används.', + 'To use memcached set CMemCache::useMemcached to true.' => 'För att använda memcached, sätt CMemCache::useMemcached till true.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Kan inte avgöra URL:ens sökvägsinfo. Kontrollera att $_SERVER["PATH_INFO"] (eller $_SERVER["PHP_SELF"] och $_SERVER["SCRIPT_NAME"]) innehÃ¥ller korrekta värden.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/ta_in/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ta_in/yii.php new file mode 100644 index 0000000..4303609 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/ta_in/yii.php @@ -0,0 +1,46 @@ + + */ +return array ( + '$_SERVER does not have {vars}.' => '$_SERVER {vars} à®à®•௠கொணà¯à®Ÿà®¿à®°à¯à®•à¯à®•விலà¯à®²à¯ˆ.', + '$_SERVER variable' => '$_SERVER மாறிலி', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] வழிதà¯à®¤à®Ÿà®®à¯ à®®à¯à®¤à®©à¯à®®à¯ˆ வழிதà¯à®¤à®Ÿà®¤à¯à®¤à®¿à®²à®¿à®°à¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯.', + 'APC extension' => 'APC நீடà¯à®šà®¿', + 'All DB-related classes' => 'தகவலà¯à®¤à®³à®®à¯ சமà¯à®ªà®¨à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿ உரà¯à®•à¯à®•ள௠அனைதà¯à®¤à¯à®®à¯', + 'DOM extension' => 'DOM நீடà¯à®šà®¿', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] அலà¯à®²à®¤à¯ $_SERVER["QUERY_STRING"] கணà¯à®Ÿà®¿à®ªà¯à®ªà®¾à®• இரà¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯.', + 'GD extension with
              FreeType support' => 'GD நீடà¯à®šà®¿
              FreeType பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯à®Ÿà®©à¯', + 'GD installed
              FreeType support not installed' => 'GD நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯
              FreeType பயனà¯à®ªà®¾à®Ÿà¯ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•விலà¯à®²à¯ˆ', + 'GD not installed' => 'GD நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•விலà¯à®²à¯ˆ', + 'Mcrypt extension' => 'Mcrypt நீடà¯à®šà®¿', + 'Memcache extension' => 'Memcache நீடà¯à®šà®¿', + 'PCRE extension' => 'PCRE நீடà¯à®šà®¿', + 'PDO MySQL extension' => 'PDO MySQL நீடà¯à®šà®¿', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL நீடà¯à®šà®¿', + 'PDO SQLite extension' => 'PDO SQLite நீடà¯à®šà®¿', + 'PDO extension' => 'PDO நீடà¯à®šà®¿', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0 அலà¯à®²à®¤à¯ மேனà¯à®®à¯ˆà®¯à®¾à®©à®¤à¯ இரà¯à®¤à¯à®¤à®²à¯ வேணà¯à®Ÿà¯à®®à¯.', + 'PHP version' => 'PHP பதிபà¯à®ªà¯', + 'Reflection extension' => 'Reflection நீடà¯à®šà®¿', + 'SOAP extension' => 'SOAP நீடà¯à®šà®¿', + 'SPL extension' => 'SPL நீடà¯à®šà®¿', + 'This is required by encrypt and decrypt methods.' => 'இத௠encrypt மறà¯à®±à¯à®®à¯ decrypt பயனà¯à®ªà®¾à®Ÿà¯à®•ளà¯à®•à¯à®•à¯à®¤à¯ தேவையானதà¯.', + 'This is required if you are using MySQL database.' => 'நீஙà¯à®•ள௠MySQL தகவலà¯à®¤à®³à®¤à¯à®¤à¯ˆ உபயோகபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®©à®¾à®²à¯ இத௠தேவையானதà¯.', + 'This is required if you are using PostgreSQL database.' => 'நீஙà¯à®•ள௠PostgreSQL தகவலà¯à®¤à®³à®¤à¯à®¤à¯ˆ உபயோகபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®©à®¾à®²à¯ இத௠தேவையானதà¯.', + 'This is required if you are using SQLite database.' => 'நீஙà¯à®•ள௠SQLite தகவலà¯à®¤à®³à®¤à¯à®¤à¯ˆ உபயோகபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®©à®¾à®²à¯ இத௠தேவையானதà¯.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'à®®à¯à®•வரியின௠தகவலà¯à®•ளைப௠பெற இயலவிலà¯à®²à¯ˆ. தயவà¯à®šà¯†à®¯à¯à®¤à¯ $_SERVER["PATH_INFO"] (அலà¯à®²à®¤à¯ $_SERVER["PHP_SELF"] மறà¯à®±à¯à®®à¯ $_SERVER["SCRIPT_NAME"]) தகவலà¯à®•ளை சரிபாரà¯à®•à¯à®•வà¯à®®à¯.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/uk/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/uk/yii.php new file mode 100644 index 0000000..4882966 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/uk/yii.php @@ -0,0 +1,50 @@ + 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ctype', + 'GD extension with
              FreeType support' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ GD із
              підтримкою FreeType', + 'GD installed
              FreeType support not installed' => 'GD вÑтановлено
              підтримку FreeType не вÑтановлено', + 'GD not installed' => 'GD не вÑтановлено', + 'To use memcached set CMemCache::useMemcached to true.' => 'Щоб викориÑтовувати memcached вÑтановіть CMemCache::useMemcached Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ true.', + 'GD extension' => '@@Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ GD@@', + '$_SERVER does not have {vars}.' => 'Змінна $_SERVER не міÑтить {vars}.', + '$_SERVER variable' => 'Змінна $_SERVER.', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => 'Змінна $_SERVER["SCRIPT_FILENAME"] повинна відповідати шлÑху до файла вхідного Ñкрипта.', + 'APC extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ APC', + 'All DB-related classes' => 'Ð’ÑÑ– DB-клаÑи', + 'DOM extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ DOM', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Повинна Ñ–Ñнувати хоча б одна з Ñерверних змінних: $_SERVER["REQUEST_URI"] або $_SERVER["QUERY_STRING"].', + 'Mcrypt extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Mcrypt', + 'Memcache extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Memcache', + 'PCRE extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ PCRE', + 'PDO MySQL extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ PDO MySQL', + 'PDO PostgreSQL extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ PDO PostgreSQL', + 'PDO SQLite extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ PDO SQLite', + 'PDO extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ PDO', + 'PHP 5.1.0 or higher is required.' => 'Ðеобхідна верÑÑ–Ñ Ð ÐР 5.1.0 або вище.', + 'PHP version' => 'ВерÑÑ–Ñ Ð ÐР', + 'Reflection extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Reflection', + 'SOAP extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ SOAP', + 'SPL extension' => 'Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ SPL', + 'This is required by encrypt and decrypt methods.' => 'Це потрібно Ð´Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ методів ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ– дешифруваннÑ.', + 'This is required if you are using MySQL database.' => 'Це потрібно Ð´Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ з БД MySQL.', + 'This is required if you are using PostgreSQL database.' => 'Це потрібно Ð´Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ з БД PostgreSQL.', + 'This is required if you are using SQLite database.' => 'Це потрібно Ð´Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ з БД SQLite.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Ðе вдалоÑÑŒ отримати інформацію про URL-шлÑÑ…. Будь лаÑка, перевірте чи міÑÑ‚ÑтьÑÑ Ð²Ñ–Ñ€Ð½Ñ– Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ змінній $_SERVER["PATH_INFO"] (або $_SERVER["PHP_SELF"] Ñ– $_SERVER["SCRIPT_NAME"]).', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/vi/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/vi/yii.php new file mode 100644 index 0000000..5ca5783 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/vi/yii.php @@ -0,0 +1,41 @@ + '$_SERVER không chứa {vars}', + '$_SERVER variable' => 'Biến $_SERVER', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] phải giống đưá»ng dẫn cá»§a file khởi động', + 'APC extension' => 'APC extension', + 'All DB-related classes' => 'Tất cả các lá»›p liên quan đến CSDL', + 'DOM extension' => 'DOM extension', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => 'Biến $_SERVER["REQUEST_URI"] hoặc $_SERVER["QUERY_STRING"] phải tồn tại.', + 'GD extension' => 'GD extension', + 'Mcrypt extension' => 'Mcrypt extension', + 'Memcache extension' => 'Memcache extension', + 'PCRE extension' => 'PCRE extension', + 'PDO MySQL extension' => 'PDO MySQl extension', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL extension', + 'PDO SQLite extension' => 'PDO SQLite extension', + 'PDO extension' => 'PDO extension', + 'PHP 5.1.0 or higher is required.' => 'Phải có PHP 5.1.0 hoặc má»›i hÆ¡n', + 'PHP version' => 'Phiên bản PHP', + 'Reflection extension' => 'Reflection extension', + 'SOAP extension' => 'SOAP extension', + 'SPL extension' => 'SPL extension', + 'This is required if you are using MySQL database.' => 'Cần phải có nếu bạn dùng MySQL', + 'This is required if you are using PostgreSQL database.' => 'Cần phải có nếu bạn dùng PostgreSQL', + 'This is required if you are using SQLite database.' => 'Cần phải có nếu bạn dùng SQLite', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'Không xác định được thông tin đưá»ng dẫn URL. Hãy kiểm tra đảm bảo $_SERVER["PATH_INFO"] (hoặc $_SERVER["PHP_SELF"] và $_SERVER["SCRIPT_NAME"]) có giá trị đúng.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/zh_cn/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/zh_cn/yii.php new file mode 100644 index 0000000..1c53e2a --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/zh_cn/yii.php @@ -0,0 +1,41 @@ + 'PHP版本', + 'PHP 5.1.0 or higher is required.' => 'PHP 5.1.0或更高版本是必须的。', + '$_SERVER variable' => '$_SERVERå˜é‡', + 'Reflection extension' => 'Reflection扩展模å—', + 'PCRE extension' => 'PCRE扩展模å—', + 'SPL extension' => 'SPL扩展模å—', + 'DOM extension' => 'DOM扩展模å—', + 'PDO extension' => 'PDO扩展模å—', + 'All DB-related classes' => '所有和数æ®åº“相关的类', + 'Memcache extension' => 'Memcache扩展模å—', + 'APC extension' => 'APC扩展模å—', + 'Mcrypt extension' => 'Mcrypt扩展模å—', + 'SOAP extension' => 'SOAP扩展模å—', + 'GD extension' => 'GD扩展模å—', + '$_SERVER does not have {vars}.' => '$_SERVER缺少{vars}。', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"]å¿…é¡»ä¸Žå…¥å£æ–‡ä»¶è·¯å¾„一致。', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"]或$_SERVER["QUERY_STRING"]必须存在。', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => '无法确定URL path info。请检查$_SERVER["PATH_INFO"](或$_SERVER["PHP_SELF"]å’Œ$_SERVER["SCRIPT_NAME"]ï¼‰çš„å€¼æ˜¯å¦æ­£ç¡®ã€‚', + 'PDO SQLite extension' => 'PDO SQLite扩展模å—', + 'This is required if you are using SQLite database.' => '如果使用SQLiteæ•°æ®åº“,这是必须的。', + 'PDO MySQL extension' => 'PDO MySQL扩展模å—', + 'This is required if you are using MySQL database.' => '如果使用MySQLæ•°æ®åº“,这是必须的。', + 'PDO PostgreSQL extension' => 'PDO PostgreSQL扩展模å—', + 'This is required if you are using PostgreSQL database.' => '如果使用PostgreSQLæ•°æ®åº“,这是必须的。', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/messages/zh_tw/yii.php b/src/common/lib/vendor/yiisoft/yii/requirements/messages/zh_tw/yii.php new file mode 100644 index 0000000..ee823b4 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/messages/zh_tw/yii.php @@ -0,0 +1,41 @@ + '$_SERVER 中沒有 {vars}.', + '$_SERVER variable' => '$_SERVER 變數', + '$_SERVER["SCRIPT_FILENAME"] must be the same as the entry script file path.' => '$_SERVER["SCRIPT_FILENAME"] 必須與入å£è…³æœ¬æª”案路徑一致.', + 'APC extension' => '', + 'All DB-related classes' => '所有 資料庫相關的類別', + 'DOM extension' => '', + 'Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must exist.' => '$_SERVER["REQUEST_URI"] 或 $_SERVER["QUERY_STRING"] 必須存在.', + 'GD extension' => '', + 'Mcrypt extension' => '', + 'Memcache extension' => '', + 'PCRE extension' => '', + 'PDO MySQL extension' => '', + 'PDO PostgreSQL extension' => '', + 'PDO SQLite extension' => '', + 'PDO extension' => '', + 'PHP 5.1.0 or higher is required.' => 'éœ€è¦ PHP 5.1.0 或之後的版本.', + 'PHP version' => 'PHP 版本', + 'Reflection extension' => '', + 'SOAP extension' => '', + 'SPL extension' => '', + 'This is required if you are using MySQL database.' => '當使用 MySQL 資料庫時, 此項為必è¦.', + 'This is required if you are using PostgreSQL database.' => '當使用 PostgreSQL 資料庫時, 此項為必è¦.', + 'This is required if you are using SQLite database.' => '當使用 SQLite 資料庫時, 此項為必è¦.', + 'Unable to determine URL path info. Please make sure $_SERVER["PATH_INFO"] (or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"]) contains proper value.' => 'ç„¡æ³•ç¢ºèª URL 路徑資訊. 請確定 $_SERVER["PATH_INFO"] (或 $_SERVER["PHP_SELF"] 與 $_SERVER["SCRIPT_NAME"]) 包å«é©ç•¶çš„值.', +); diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/.htaccess b/src/common/lib/vendor/yiisoft/yii/requirements/views/.htaccess new file mode 100644 index 0000000..e019832 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/ar/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/ar/index.php new file mode 100644 index 0000000..097f1e3 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/ar/index.php @@ -0,0 +1,74 @@ + + + + + + +مدقق متطلبات Yii + + + +
              + + + +
              +

              الوصÙ

              +

              +يتحقق هذا السكربت ماإذا كانت إعدادات الخادم لديك تÙÙŠ بمتطلبات تشغيل تطبيقات الويب لاطار العمل Yii. +يتحقق ايضا ما إذا كان الخادم يعمل على الإصدارة الصحيحة من PHPØŒ +تحميل اللاحقات المناسبة، وأيضا ما إذا كانت إعدادات مل٠php.ini صحيحة. +

              + +

              النتيجة

              +

              +0): ?> +تهانينا! إعدادات الخادم لديك مستوÙية جميع متطلبات تشغيل Yii. + +إعدادات الخادم الخاص بك مستوÙية للحد الادنى لمتطلبات تشغيل Yii. الرجاء ملاحظة قائمة التنبيهات أدناه وما إذا كان التطبيق الخاص بك يستخدم أحد هذه المزايا. + +لسوء الحظ إعدادات الخادم الخاص بك لا تلبي متطلبات تشغيل Yii. + +

              + +

              Ø§Ù„ØªÙØ§ØµÙŠÙ„

              + + + + + + + + + + + +
              الاسمالنتيجةمطلوب من قبلملاحظات
              + + + + + + + +
              + + + + + + + +
               Ù†Ø¬Ø­ Ùشل ØªÙ†Ø¨ÙŠÙ‡
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/bg/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/bg/index.php new file mode 100644 index 0000000..44d5f87 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/bg/index.php @@ -0,0 +1,81 @@ + + + + + + +Yii Requirement Checker + + + +
              + + + +
              +

              ОпиÑание

              +

              +This script checks if your server configuration meets the requirements +for running Yii Web applications. +It checks if the server is running the right version of PHP, +if appropriate PHP extensions have been loaded, and if php.ini file settings are correct. + +Този Ñкрипт проверÑва дали конфигурациÑта на вавиÑÑ‚ Ñървър, Ð¾Ñ‚Ð³Ð¾Ð²Ð°Ñ€Ñ Ð½Ð° изиÑкваниÑта за +работа на Yii уеб приложениÑта. +ПроверÑва дали на Ñървъра работи подходÑщата верÑÐ¸Ñ Ð½Ð° PHP, +дали подходÑщите PHP добавки Ñа заредени и дали наÑтройките в php.ini Ñа вÑрни +

              + +

              Заключение

              +

              +0): ?> +Congratulations! Your server configuration satisfies all requirements by Yii. +Поздравление! ВашиÑÑ‚ Ñървър Ð¾Ñ‚Ð³Ð¾Ð²Ð°Ñ€Ñ Ð½Ð° вÑики изиÑÐºÐ²Ð°Ð½Ð¸Ñ Ð·Ð° работа на Yii. + +ВашиÑÑ‚ Ñървър удоблетворÑва минималните изиÑÐºÐ²Ð°Ð½Ð¸Ñ Ð½Ð° Yii. МолÑ, обърнете внимание на ÑпиÑъка Ñ Ð³Ñ€ÐµÑˆÐºÐ¸ отдоло, ако вашето приложение ще използва тези функции. + +За жалоÑÑ‚, вашиÑÑ‚ Ñървър, не Ð¾Ñ‚Ð³Ð¾Ð²Ð°Ñ€Ñ Ð½Ð° изиÑкваниÑта за работа на Yii. + +

              + +

              Детайли

              + + + + + + + + + + + +
              ИмеРезултатПоиÑкано отБележка
              + + + + + + + +
              + + + + + + + +
               Ð¿Ñ€ÐµÐ¼Ð¸Ð½Ð°Ñ‚ Ð¿Ñ€Ð¾Ð²Ð°Ð»ÐµÐ½ Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ðµ
              + +
              + + + +
              + + diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/ca/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/ca/index.php new file mode 100644 index 0000000..73a2d16 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/ca/index.php @@ -0,0 +1,74 @@ + + + + + + +Verificació de requerimients de Yii + + + +
              + + + +
              +

              Descripció

              +

              +Aquest script verifica que la configuració del seu servidor compleix amb els requeriments necessàris per poder executar aplicacions Web Yii. +El mateix verifica que el servidor corre una versió adequada de PHP, que les extensions PHP necessàries han set carregades i que les configuracions de l'arxiu php.ini són correctes. +

              + +

              Conclusió

              +

              +0): ?> +Enhorabona! El vostre servidor compleix tots els requeriments de Yii. + +La configuració del vostre servidor compleix els requeriments mínims de Yii. Si us plau, prengui atenció a les advertències llistades a continuació si la seva aplicació utilitza alguna d'aquestes característiques. + +Desafortunadamente la configuración de su servidor no satisface los requerimientos de Yii. +Desafortunamadament, la configuració del vostre servidor no compleix els requeriments de Yii. + +

              + +

              Detalles

              + + + + + + + + + + + +
              NomResultatRequerit perMemo
              + + + + + + + +
              + + + + + + + +
               correcte error advertència
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/de/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/de/index.php new file mode 100644 index 0000000..b1db4ed --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/de/index.php @@ -0,0 +1,76 @@ + + + + + + +Yii Anforderungs-Tester + + + +
              + + + +
              +

              Beschreibung

              +

              +Dieses Script ermittelt, ob Ihre Serverkonfiguration die Anforderungen zum +Ausführen von Yii Webanwendungen +erfüllt. +Es prüft auf die korrekte PHP Version, ob die benötigten Erweiterungen +geladen wurden und ob die Einstellungen in der php.ini korrekt sind +

              + +

              Zusammenfassung

              +

              +0): ?> +Gratulation! Ihr Server erfüllt alle Anforderungen von Yii. + +Ihr Server erfüllt die minimalen Anforderungen von Yii. Bitte beachten Sie die untenstehenden Warnungen, wenn Ihre Anwendungen einige dieser Features verwenden sollen. + +Unglücklicherweise erfüllt Ihr Server die Anforderungen von Yii nicht. + +

              + +

              Details

              + + + + + + + + + + + +
              NameResultatBenötigt vonMemo
              + + + + + + + +
              + + + + + + + +
               Bestanden Verfehlt Warnung
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/de_de/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/de_de/index.php new file mode 100644 index 0000000..b1db4ed --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/de_de/index.php @@ -0,0 +1,76 @@ + + + + + + +Yii Anforderungs-Tester + + + +
              + + + +
              +

              Beschreibung

              +

              +Dieses Script ermittelt, ob Ihre Serverkonfiguration die Anforderungen zum +Ausführen von Yii Webanwendungen +erfüllt. +Es prüft auf die korrekte PHP Version, ob die benötigten Erweiterungen +geladen wurden und ob die Einstellungen in der php.ini korrekt sind +

              + +

              Zusammenfassung

              +

              +0): ?> +Gratulation! Ihr Server erfüllt alle Anforderungen von Yii. + +Ihr Server erfüllt die minimalen Anforderungen von Yii. Bitte beachten Sie die untenstehenden Warnungen, wenn Ihre Anwendungen einige dieser Features verwenden sollen. + +Unglücklicherweise erfüllt Ihr Server die Anforderungen von Yii nicht. + +

              + +

              Details

              + + + + + + + + + + + +
              NameResultatBenötigt vonMemo
              + + + + + + + +
              + + + + + + + +
               Bestanden Verfehlt Warnung
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/el/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/el/index.php new file mode 100644 index 0000000..eaf1896 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/el/index.php @@ -0,0 +1,75 @@ + + + + + + +Ελεγκτής Απαιτήσεων Yii + + + +
              + + + +
              +

              ΠεÏιγÏαφή

              +

              +Αυτή η σελίδα ελέγχει αν η παÏαμετÏοποίηση του διακομιστή σας είναι σωστή +για την εκτέλεση των εφαÏμογών Î¹ÏƒÏ„Î¿Ï Ï„Î¿Ï… Yii. +Ελέγχει αν ο διακομιστής εκτελεί τη σωστή έκδοση PHP, αν έχουν φοÏτωθεί +οι κατάλληλες επεκτάσεις PHP και αν οι Ïυθμίσεις του αÏχείου php.ini είναι σωστές. +

              + +

              ΣυμπέÏασμα

              +

              +0): ?> +ΣυγχαÏητήÏια! Η παÏαμετÏοποίηση του διακομιστή σας ικανοποιεί όλες τις απαιτήσεις του Yii. + +Η παÏαμετÏοποίηση του διακομιστή σας ικανοποιεί τις ελάχιστες απαιτήσεις του Yii. ΠαÏακαλοÏμε δείτε με Ï€Ïοσοχή τις παÏακάτω Ï€Ïοειδοποιήσεις εφόσον η εφαÏμογή σας θα χÏησιμοποιεί τα αντίστοιχα χαÏακτηÏιστικά. + +Δυστυχώς, η παÏαμετÏοποίηση του διακομιστή σας δεν ικανοποιεί τις απαιτήσεις του Yii. + +

              + +

              ΛεπτομέÏειες

              + + + + + + + + + + + +
              ΌνομαΑποτέλεσμαΑπαιτοÏμενο απόΣημειώσεις
              + + + + + + + +
              + + + + + + + +
               Ï€Î­Ïασε Î±Ï€Î­Ï„υχε Ï€Ïοειδοποίηση
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/es/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/es/index.php new file mode 100644 index 0000000..4aafbe2 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/es/index.php @@ -0,0 +1,75 @@ + + + + + + +Verificación de requerimientos de Yii + + + +
              + + + +
              +

              Descripción

              +

              +Este script verifica que la configuración de su servidor cumpla con los requerimientos +para poder ejecutar aplicaciones Web Yii. +El mismo verifica que el servidor este corriendo una versión adecuada de PHP, +que las extensiones PHP necesarias hayan sido cargadas y que las configuraciones del archivo php.ini sean correctas. +

              + +

              Conclusión

              +

              +0): ?> +Felicitaciones! Su servidor satisface todos los requerimientos de Yii. + +La configuración de su servidor satisface los requerimientos mínimos de Yii. Por favor preste atención a las advertencias listadas en el cuadro más abajo si su aplicación utiliza alguna de esas características. + +Desafortunadamente la configuración de su servidor no satisface los requerimientos de Yii. + +

              + +

              Detalles

              + + + + + + + + + + + +
              NombreResultadoRequerido porMemo
              + + + + + + + +
              + + + + + + + +
               paso fallo advertencia
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/fr/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/fr/index.php new file mode 100644 index 0000000..614c5a3 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/fr/index.php @@ -0,0 +1,75 @@ + + + + + + +Vérification de la configuration nécessaire pour Yii + + + +
              + + + +
              +

              Description

              +

              +Ce script vérifie si la configuration de votre serveur satisfait toutes les dépendances nécessaires +pour exécuter les applications Yii. +Il vérifie si le serveur exécute la version correcte de PHP, +si toutes les extensions PHP nécessaires ont été chargées, et si les paramètres du fichier php.ini sont corrects +

              + +

              Conclusion

              +

              +0): ?> +Félicitations ! Votre configuration vérifie toutes les exigences de Yii. + +Votre configuration satisfait les exigences minimales de Yii. Notez les avertissements listés ci-dessous si votre application utilise les fonctionnalités correspondantes. + +Malheureusement, votre configuration ne satisfait pas les exigences de Yii. + +

              + +

              Details

              + + + + + + + + + + + +
              NomResultatRequis ParInfo
              + + + + + + + +
              + + + + + + + +
               Ok Echec Avertissement
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/he/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/he/index.php new file mode 100644 index 0000000..35ac94d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/he/index.php @@ -0,0 +1,76 @@ + + + + + + +בדיקת דרישות ×ž×™× ×™×ž×•× ×œ×”×¨×¦×ª Yii + + + +
              + + + +
              +

              תי×ור

              +

              +הסקריפט ×”×‘× ×‘×•×“×§ ×× ×¡×‘×™×‘×ª השרת שלך תוכל לעמוד בדרישות ×”×ž×™× ×™×ž×•× ×›×“×™ להריץ ×ת + Yii לפיתוח מערכות ווב מתקדמות. +הסקריפט בודק ×× ×”×©×¨×ª מריץ גרס×ת PHP עדכנית, +×× ×”×¨×—×‘×•×ª מסויימת קיימות ב PHP ונטענו בהצלחה, ו×× ×”×’×“×¨×•×ª ×” php.ini מוגדרות כמו שצריך. +

              + +

              סיכו×

              +

              +0): ?> +ברכותיינו! סביבת השרת שלך תומכת בכל הגדרישות של Yii. + +הגדרות סביבת השרת שלך מת×ימות לדרישות ×”×ž×™× ×™×ž×•× ×©×œ Yii. + ×× × ×©×™× ×œ×‘ ל×זהרות והערות הכתובות מטה במידה וה×פליקציה שתכתוב תשתמש ב×חת מה×פשרויות הללו. + +לצערנו סביבת השרת שלך ××™× ×” תומכת בדרישות ×”×ž×™× ×™×ž×•× ×©×œ Yii. + +

              + +

              פרטי×

              + + + + + + + + + + + +
              כותרתתוצ×הנדרש על ידיתזכורת
              + + + + + + + +
              + + + + + + + +
               ×¢×‘ר × ×›×©×œ ×זהרה
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/index.php new file mode 100644 index 0000000..15f2211 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/index.php @@ -0,0 +1,75 @@ + + + + + + +Yii Requirement Checker + + + +
              + + + +
              +

              Description

              +

              +This script checks if your server configuration meets the requirements +for running Yii Web applications. +It checks if the server is running the right version of PHP, +if appropriate PHP extensions have been loaded, and if php.ini file settings are correct. +

              + +

              Conclusion

              +

              +0): ?> +Congratulations! Your server configuration satisfies all requirements by Yii. + +Your server configuration satisfies the minimum requirements by Yii. Please pay attention to the warnings listed below if your application will use the corresponding features. + +Unfortunately your server configuration does not satisfy the requirements by Yii. + +

              + +

              Details

              + + + + + + + + + + + +
              NameResultRequired ByMemo
              + + + + + + + +
              + + + + + + + +
               passed failed warning
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/it/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/it/index.php new file mode 100644 index 0000000..c87990b --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/it/index.php @@ -0,0 +1,75 @@ + + + + + + +Verifica soddisfazione requisiti di Yii + + + +
              + + + +
              +

              Descrizione

              +

              +Questo script verifica se la configurazione del tuo server soddisfa i requisiti +di esecuzione delle web application sviluppate con Yii. +Verifica se nel server è in esecuzione la corretta versione di PHP, se le +estensioni PHP necessarie sono state caricate e se le impostazioni di php.ini sono corrette. +

              + +

              Conclusioni

              +

              +0): ?> +Congratulazioni! La configurazione del tuo server soddisfa tutti i requisiti di Yii. + +La configurazione del tuo server soddisfa i requisiti minimi di Yii. Si prega di prestare attenzione agli avvisi qui sotto qualora l'applicazione utilizzi le corrispondenti funzionalità. + +Sfortunatamente La configurazione del tuo server non soddisfa i requisiti di Yii. + +

              + +

              Dettagli

              + + + + + + + + + + + +
              NomeResultatoRichiesto daMemo
              + + + + + + + +
              + + + + + + + +
               superato fallito avviso
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/ja/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/ja/index.php new file mode 100644 index 0000000..04202c1 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/ja/index.php @@ -0,0 +1,74 @@ + + + + + + +Yii å¿…è¦æ¡ä»¶ãƒã‚§ãƒƒã‚« + + + +
              + + + +
              +

              説明

              +

              +ã“ã®ã‚¹ã‚¯ãƒªãƒ—トã¯ã€ã‚ãªãŸã®ã‚µãƒ¼ãƒæ§‹æˆãŒ Yii +ウェブアプリケーションを実行ã™ã‚‹å¿…è¦æ¡ä»¶ã‚’満ãŸã—ã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’確èªã™ã‚‹ã‚‚ã®ã§ã™ã€‚ +ã™ãªã‚ã¡ã€ã‚µãƒ¼ãƒãŒæ­£ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® PHP を実行ã—ã¦ã„ã‚‹ã‹ã€é©åˆ‡ãª PHP 拡張をロードã—ã¦ã„ã‚‹ã‹ã€php.ini ファイルã®è¨­å®šãŒæ­£ã—ã„ã‹ã€ã‚’確èªã—ã¾ã™ã€‚

              + +

              åˆ¤å®šçµæžœ

              +

              +0): ?> +ãŠã‚ã§ã¨ã†ã”ã–ã„ã¾ã™ã€‚ã‚ãªãŸã®ã‚µãƒ¼ãƒæ§‹æˆã¯ Yii ã®å…¨ã¦ã®å¿…è¦æ¡ä»¶ã‚’満ã—ã¦ã„ã¾ã™ã€‚ + +ã‚ãªãŸã®ã‚µãƒ¼ãƒæ§‹æˆã¯ Yii ã®æœ€ä½Žé™ã®å¿…è¦æ¡ä»¶ã‚’満ã—ã¦ã„ã¾ã™ã€‚ +「注æ„ã€ãŒå‡ºã¦ã„ã‚‹é …ç›®ã«ã¤ã„ã¦ã€ã‚ãªãŸã®ã‚¢ãƒ—リケーションãŒå¯¾å¿œã™ã‚‹æ©Ÿèƒ½ã‚’使用ã™ã‚‹äºˆå®šãŒæœ‰ã‚‹ã‹ç„¡ã„ã‹ã‚’確èªã—ã¦ãã ã•ã„。 + +残念ã§ã™ãŒã€ã‚ãªãŸã®ã‚µãƒ¼ãƒæ§‹æˆã¯ Yii ã®å¿…è¦æ¡ä»¶ã‚’満ã—ã¦ã„ã¾ã›ã‚“。 + +

              + +

              詳細

              + + + + + + + + + + + +
              åç§°çµæžœå¯¾å¿œã™ã‚‹æ©Ÿèƒ½å‚™è€ƒ
              + + + + + + + +
              + + + + + + + +
               åˆæ ¼ ä¸åˆæ ¼ æ³¨æ„
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/no/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/no/index.php new file mode 100644 index 0000000..1c63ac3 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/no/index.php @@ -0,0 +1,77 @@ + + + + + + +Yii - Sjekk systemkrav + + + +
              + + + +
              +

              Beskrivelse

              +

              +Dette skriptet sjekker om serverkonfigurasjonen oppfyller kravene for å kjøre +Yii-applikasjoner. +Det sjekker om serveren kjører riktig versjon av PHP, om nødvendige extensions +er lastet og om PHP-innstillingene i php.ini er korrekt. +

              + +

              Konklusjon

              +

              +0): ?> +Gratulerer! Konfigurasjonen på serveren tilfredstiller alle krav for å kjøre Yii. + +Konfigurasjonen på serveren tilfredstiller minimumskravene til Yii. Vær oppmerksom +på advarslene listet nedenfor dersom applikasjonen din trenger noe av denne +funksjonaliteten. + +Desverre tilfredstiller ikke konfigurasjonen av serveren minimumskravene til Yii. + +

              + +

              Detaljer

              + + + + + + + + + + + +
              NavnResultatKreves avNotat
              + + + + + + + +
              + + + + + + + +
               ok feil advarsel
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/pl/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/pl/index.php new file mode 100644 index 0000000..f5bfd84 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/pl/index.php @@ -0,0 +1,76 @@ + + + + + + +Sprawdzanie wymagań przez Yii + + + +
              + + + +
              +

              Opis

              +

              +Skrypt ten sprawdza czy konfiguracja Twojego serwera spełnia wymagania +pozwalające uruchomić aplikację napisaną przy użyciu Yii. +Sprawdza on, czy serwer używa poprawnej wersji PHP, +czy zostały załadowane odpowiednie rozszerzenia PHP oraz czy ustawienia w pliku php.ini są prawidłowe. +

              + +

              Rozstrzygnięcie

              +

              +0): ?> +Gratulacje! Konfiguracja Twojego serwera spełnia wszystkie wymagania stawiane przez Yii. + +Konfiguracja Twojego serwera spełnia minimalne wymagania stawiane przez Yii. +Zwróć uwagę na ostrzeżenia wyświetlone poniżej jeśli Twoja aplikacja będzie używała odpowiadających im funkcjonalności. + +Niestety konfiguracja Twojego serwera nie spełnia wymagań stawianych przez Yii. + +

              + +

              Szczegóły

              + + + + + + + + + + + +
              NazwaRezultatWymagana przezNotka
              + + + + + + + +
              + + + + + + + +
               powiódÅ‚ siÄ™ nie powiódÅ‚ siÄ™ ostrzeżenie
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/pt/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/pt/index.php new file mode 100644 index 0000000..51426a7 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/pt/index.php @@ -0,0 +1,76 @@ + + + + + + +Verificador de requisitos do Yii + + + +
              + + + +
              +

              Descrição

              +

              +Este script verifica se as configurações do servidor satisfazem os requisitos +para executar aplicações Web que utilizem o Yii . +É verificado se o servidor está executando a versão correta do PHP, +se as extensões apropriadas do PHP foram carregadas, +e se as definições do arquivo php.ini estão corretas. +

              + +

              Resultados

              +

              +0): ?> +Parabéns! As configurações do seu servidor satisfazem todos os requisitos do Yii. + +As configurações do seu servidor satisfazem os requisitos mínimos do Yii. Por favor, preste atenção às advertências listados abaixo caso sua aplicação irá utilizar os recursos correspondentes. + +Infelizmente o as configurações do seu servidor não satisfazem os requisitos do Yii. + +

              + +

              Detalhes

              + + + + + + + + + + + +
              NomeResultadoExigido porDetalhe
              + + + + + + + +
              + + + + + + + +
               OK Falhou Advertência
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/pt_br/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/pt_br/index.php new file mode 100644 index 0000000..8538d70 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/pt_br/index.php @@ -0,0 +1,76 @@ + + + + + + +Verificador de requisitos do Yii + + + +
              + + + +
              +

              Descrição

              +

              +Este script verifica se as configurações do servidor satisfazem os requisitos +para executar aplicações Web que utilizem o Yii . +É verificado se o servidor está executando a versão correta do PHP, +se as extensões apropriadas do PHP foram carregadas, +e se as definições do arquivo php.ini estão corretas. +

              + +

              Resultados

              +

              +0): ?> +Parabéns! As configurações do seu servidor satisfazem todos os requisitos do Yii. + +As configurações do seu servidor satisfazem os requisitos mínimos do Yii. Por favor, preste atenção às advertências listadas abaixo caso sua aplicação for utilizar os recursos correspondentes. + +Infelizmente as configurações do seu servidor não satisfazem os requisitos do Yii. + +

              + +

              Detalhes

              + + + + + + + + + + + +
              NomeResultadoExigido porDetalhe
              + + + + + + + +
              + + + + + + + +
               OK Falhou Advertência
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/ro/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/ro/index.php new file mode 100644 index 0000000..2d83da2 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/ro/index.php @@ -0,0 +1,78 @@ + + + + + + +Verificare cerinte Yii + + + +
              + + + +
              +

              Descriere

              +

              +Acest script verifica daca configuratia serverului dvs indeplineste cerintele +pentru rularea aplicatiilor Web Yii. +Se fac urmatoarele verificari: daca serverul ruleaza versiunea corecta de PHP, +daca extensiile PHP corespunzatoare au fost incarcate si daca +setarile din fisierul php.ini sunt corecte. +

              + +

              Concluzie

              +

              +0): ?> +Felicitari! Configuratia serverului dvs indeplineste toate cerintele Yii. + +Configuratia serverului dvs indeplineste cerintele minime pentru Yii. +Va rugam sa cititi avertismentele afisate mai jos, in cazul in care aplicatia pe care o veti crea +va folosi respectivele feature-uri. + +Din pacate, configuratia serverului dvs nu indeplineste cerintele Yii. + +

              + +

              Detalii

              + + + + + + + + + + + +
              NumeRezultatCerut dePrecizari
              + + + + + + + +
              + + + + + + + +
               passed failed warning
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/ru/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/ru/index.php new file mode 100644 index 0000000..90064fe --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/ru/index.php @@ -0,0 +1,75 @@ + + + + + + +Проверка на ÑоответÑтвие требованиÑм Yii + + + +
              + + + +
              +

              ОпиÑание

              +

              +Данный Ñкрипт проверÑет ÑоответÑтвие конфигурации Вашего веб-Ñервера требованиÑм, +предъÑвлÑемым веб-приложениÑми Yii. +Ð’ чаÑтноÑти, проверÑÑŽÑ‚ÑÑ Ð²ÐµÑ€ÑÐ¸Ñ Ð ÐР и загруженные раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð ÐР, а также +корректноÑть наÑтроек файла php.ini. +

              + +

              Заключение

              +

              +0): ?> +ПоздравлÑем! ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ веб-Ñервера полноÑтью удовлетворÑет требованиÑм Yii. + +ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ веб-Ñервера удовлетворÑет минимально необходимым требованиÑм Yii. Обратите внимание на Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð² таблице ниже, еÑли предполагаетÑÑ Ð¸Ñпользование ÑоответÑтвующего функционала. + +К Ñожалению, ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ веб-Ñервера не удовлетворÑет требованиÑм Yii. + +

              + +

              Результаты проверки

              + + + + + + + + + + + +
              ÐазваниеИтогТребуетÑÑ Ð´Ð»ÑПоÑÑнение
              + + + + + + + +
              + + + + + + + +
               Ð”а Ðет ÐŸÑ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ðµ
              + +
              + + + +
              + + diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/sk/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/sk/index.php new file mode 100644 index 0000000..0152bbc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/sk/index.php @@ -0,0 +1,76 @@ + + + + + + +Yii - Test prostredia + + + +
              + + + +
              +

              Popis

              +

              +Tento skript preverí, Äi je konfigurácia vášho servera postaÄujúca +pre korektné fungovanie aplikácii vytvorených pre Yii framework. +Test preveruje správnu verziu PHP, prítomnosÅ¥ potrebných PHP rozšírení a správne nastavenie +konfigurácie v php.ini. +

              + +

              Záver

              +

              +0): ?> +Gratulujem! Váš server spĺňa všetky požiadavky potrebné pre korektné fungovanie Yii. + +Váš server spĺňa minimálne požiadavky potrebné pre fungovanie Yii. +Venujte prosím pozornosť upozorneniam uvedeným nižšie v prípade, že vaša aplikácia bude využívať potrebné funkcie. + +Bohužiaľ, váš server nespĺňa požiadavky potrebné pre fungovanie Yii. + +

              + +

              Detaily

              + + + + + + + + + + + +
              NázovVýsledokPožadované odPozn.
              + + + + + + + +
              + + + + + + + +
               OK chyba upozornenie
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/sv/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/sv/index.php new file mode 100644 index 0000000..7032076 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/sv/index.php @@ -0,0 +1,74 @@ + + + + + + +Yii - Kontroll systemkrav + + + +
              + + + +
              +

              Beskrivning

              +

              +Det här skriptet kontrollerar om serverkonfigurationen uppfyller kraven för att köra Yii webbapplikationer. +Det kollar att servern kör rätt version av PHP, +att erforderliga PHP-tillägg är laddade, och att inställningar i filen php.ini är korrekta. +

              + +

              Slutsats

              +

              +0): ?> +Grattis! Serverkonfigurationen uppfyller alla krav som Yii ställer. + +Serverkonfigurationen uppfyller minimikraven som Yii ställer. Lägg märke till nedanstående varningar om applikationer behöver använda nämnda finesser. + +Tyvärr uppfyller inte serverkonfigurationen minimikraven Yii ställer. + +

              + +

              Detaljer

              + + + + + + + + + + + +
              NamnResultatKrävs förMemo
              + + + + + + + +
              + + + + + + + +
               passed failed warning
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/uk/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/uk/index.php new file mode 100644 index 0000000..08acacf --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/uk/index.php @@ -0,0 +1,75 @@ + + + + + + +Перевірка на відповідніÑть до вимог Yii + + + +
              + + + +
              +

              ОпиÑ

              +

              +Цей Ñкрипт перевірÑÑ” чи відповідає ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð’Ð°ÑˆÐ¾Ð³Ð¾ веб-Ñервера вимогам, +що виÑуваютьÑÑ Ð´Ð¾ Yii веб-додатків. +Зокрема перевірÑєтьÑÑ Ð²ÐµÑ€ÑÑ–Ñ PHP, чи завантажені необхідні Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ PHP, +а також коректніÑть налаштувань у файлі php.ini. +

              + +

              ВиÑновок

              +

              +0): ?> +Вітаємо! ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð’Ð°ÑˆÐ¾Ð³Ð¾ веб-Ñервера задовольнÑÑ” вÑÑ– вимоги Yii. + +ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð’Ð°ÑˆÐ¾Ð³Ð¾ веб-Ñервера задовольнÑÑ” мінімально необхідні вимоги Yii. Зверніть увагу на Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ñƒ табличці нижче, Ñкщо передбачаєтьÑÑ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¸Ñ… функцій. + +Ðа жаль, ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð’Ð°ÑˆÐ¾Ð³Ð¾ веб-Ñервера не задовольнÑÑ” вимоги Yii. + +

              + +

              Результати перевірки

              + + + + + + + + + + + +
              ÐазваРезультатВимагаєтьÑÑ Ð´Ð»ÑПоÑÑненнÑ
              + + + + + + + +
              + + + + + + + +
               Ð¢Ð°Ðº ÐÑ– ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/zh/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/zh/index.php new file mode 100644 index 0000000..c88a7a7 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/zh/index.php @@ -0,0 +1,72 @@ + + + + + + +Yiié…置需求检查 + + + +
              + + + +
              +

              检查内容

              +

              +本网页用于确认您的æœåС噍é…置是å¦èƒ½æ»¡è¶³è¿è¡ŒYii Webåº”ç”¨çš„è¦æ±‚。它将检查æœåŠ¡å™¨æ‰€è¿è¡Œçš„PHP版本,查看是å¦å®‰è£…了åˆé€‚çš„PHP扩展模å—,以åŠç¡®è®¤php.iniæ–‡ä»¶æ˜¯å¦æ­£ç¡®è®¾ç½®ã€‚ +

              + +

              检查结果

              +

              +0): ?> +æ­å–œï¼æ‚¨çš„æœåŠ¡å™¨é…置完全符åˆYiiçš„è¦æ±‚。 + +您的æœåС噍é…置符åˆYiiçš„æœ€ä½Žè¦æ±‚。如果您需è¦ä½¿ç”¨ç‰¹å®šçš„功能,请关注如下警告。 + +您的æœåС噍é…置未能满足Yiiçš„è¦æ±‚。 + +

              + +

              具体结果

              + + + + + + + + + + + +
              项目å称结果使用者备注
              + + + + + + + +
              + + + + + + + +
               é€šè¿‡ æœªé€šè¿‡ è­¦å‘Š
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/zh_cn/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/zh_cn/index.php new file mode 100644 index 0000000..9b940dc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/zh_cn/index.php @@ -0,0 +1,72 @@ + + + + + + +Yiié…置需求检查 + + + +
              + + + +
              +

              检查内容

              +

              +本网页用于确认您的æœåС噍é…置是å¦èƒ½æ»¡è¶³è¿è¡ŒYii Webåº”ç”¨çš„è¦æ±‚。它将检查æœåŠ¡å™¨æ‰€è¿è¡Œçš„PHP版本,查看是å¦å®‰è£…了åˆé€‚çš„PHP扩展模å—,以åŠç¡®è®¤php.iniæ–‡ä»¶æ˜¯å¦æ­£ç¡®è®¾ç½®ã€‚ +

              + +

              检查结果

              +

              +0): ?> +æ­å–œï¼æ‚¨çš„æœåŠ¡å™¨é…置完全符åˆYiiçš„è¦æ±‚。 + +您的æœåС噍é…置符åˆYiiçš„æœ€ä½Žè¦æ±‚。如果您需è¦ä½¿ç”¨ç‰¹å®šçš„功能,请关注如下警告。 + +您的æœåС噍é…置未能满足Yiiçš„è¦æ±‚。 + +

              + +

              具体结果

              + + + + + + + + + + + +
              项目å称结果使用者备注
              + + + + + + + +
              + + + + + + + +
               é€šè¿‡ æœªé€šè¿‡ è­¦å‘Š
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/requirements/views/zh_tw/index.php b/src/common/lib/vendor/yiisoft/yii/requirements/views/zh_tw/index.php new file mode 100644 index 0000000..f059969 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/requirements/views/zh_tw/index.php @@ -0,0 +1,72 @@ + + + + + + +Yii系統需求檢查 + + + +
              + + + +
              +

              檢查內容說明

              +

              +本網é ç”¨æ–¼ç¢ºèªæ‚¨çš„伺æœå™¨çµ„態設定是å¦èƒ½æ»¿è¶³åŸ·è¡ŒYii Web應用程å¼çš„è¦æ±‚. 它將檢查伺æœå™¨æ˜¯å¦ä½¿ç”¨æ­£ç¢ºçš„PHP版本, 是å¦å®‰è£äº†åˆé©çš„PHP extension, 以åŠç¢ºèªphp.iniæª”æ¡ˆæ˜¯å¦æ­£ç¢ºè¨­å®š. +

              + +

              æª¢æŸ¥çµæžœ

              +

              +0): ?> +æ­å–œ! 您的伺æœå™¨çµ„態設定完全符åˆYiiçš„è¦æ±‚. + +您的伺æœå™¨çµ„態設定符åˆYiiçš„æœ€ä½Žè¦æ±‚. 請注æ„下列警告(å¦‚æžœæ‚¨çš„æ‡‰ç”¨ç¨‹å¼æœƒéœ€è¦ä½¿ç”¨åˆ°ç›¸é—œåŠŸèƒ½). + +您的伺æœå™¨çµ„態設定未能滿足Yiiçš„è¦æ±‚. + +

              + +

              è©³ç´°çµæžœ

              + + + + + + + + + + + +
              é …ç›®åç¨±çµæžœä½¿ç”¨è€…備註
              + + + + + + + +
              + + + + + + + +
               é€šéŽ æœªé€šéŽ è­¦å‘Š
              + +
              + + + +
              + + \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/TestApplication.php b/src/common/lib/vendor/yiisoft/yii/tests/TestApplication.php new file mode 100644 index 0000000..a23b0ce --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/TestApplication.php @@ -0,0 +1,63 @@ +removeDirectory($this->getRuntimePath()); + $this->removeDirectory($this->getAssetPath()); + } + + protected function removeDirectory($path) + { + if(is_dir($path) && ($folder=@opendir($path))!==false) + { + while($entry=@readdir($folder)) + { + if($entry[0]==='.') + continue; + $p=$path.DIRECTORY_SEPARATOR.$entry; + if(is_dir($p)) + $this->removeDirectory($p); + @unlink($p); + } + @closedir($folder); + } + } + + public function getAssetPath() + { + return dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'; + } + + public function getRuntimePath() + { + return dirname(__FILE__).DIRECTORY_SEPARATOR.'runtime'; + } + + public function getBasePath() + { + return dirname(__FILE__); + } + + public function setBasePath($value) + { + } + + public function loadGlobalState() + { + parent::loadGlobalState(); + } + + public function saveGlobalState() + { + parent::saveGlobalState(); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/TestHttpRequest.php b/src/common/lib/vendor/yiisoft/yii/tests/TestHttpRequest.php new file mode 100644 index 0000000..e26a661 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/TestHttpRequest.php @@ -0,0 +1,29 @@ +myScriptUrl; + } + + public function setScriptUrl($value) + { + $this->myScriptUrl=$value; + } + + public function getPathInfo() + { + return $this->myPathInfo; + } + + public function setPathInfo($value) + { + $this->myPathInfo=$value; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/assets/.gitignore b/src/common/lib/vendor/yiisoft/yii/tests/assets/.gitignore new file mode 100644 index 0000000..5e4debc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/assets/.gitignore @@ -0,0 +1 @@ +* diff --git a/src/common/lib/vendor/yiisoft/yii/tests/bootstrap.php b/src/common/lib/vendor/yiisoft/yii/tests/bootstrap.php new file mode 100644 index 0000000..c1ed85d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/bootstrap.php @@ -0,0 +1,27 @@ +_text; + } + + public function setText($value) + { + return $this->_text=$value; + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/BehaviorTestController.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/BehaviorTestController.php new file mode 100644 index 0000000..27fa9b7 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/BehaviorTestController.php @@ -0,0 +1,14 @@ +raiseEvent("onTestEvent", new CEvent()); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CApplicationComponentTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CApplicationComponentTest.php new file mode 100644 index 0000000..b6a4c6c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CApplicationComponentTest.php @@ -0,0 +1,13 @@ +getMockForAbstractClass('CApplicationComponent',array('init','getIsInitialized'),'',NULL); + $c->expects($this->any()) + ->method('getIsInitialized') + ->will($this->returnValue(FALSE)); + $this->assertFalse($c->getIsInitialized()); + $c->init(); + $this->assertTrue($c->getIsInitialized()); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CBehaviorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CBehaviorTest.php new file mode 100644 index 0000000..d973580 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CBehaviorTest.php @@ -0,0 +1,95 @@ +attachBehavior('a',new NewBehavior); + $this->assertFalse($component->behaviorCalled); + $this->assertFalse(method_exists($component,'test')); + $this->assertEquals(2,$component->test()); + $this->assertTrue($component->behaviorCalled); + $this->setExpectedException('CException'); + $component->test2(); + } + + public function testDisableBehaviors(){ + $component=new NewComponent; + $component->attachBehavior('a',new NewBehavior); + $component->disableBehaviors(); + $this->setExpectedException('CException'); + // test should not be called since behavior is disabled + echo $component->test(); + } + + /** + * Since disableBehaviors() was called, validate() should not call beforeValidate() from behavior. + * @return void + */ + public function testDisableBehaviorsAndModels(){ + $model = new NewFormModel(); + $model->disableBehaviors(); + $model->validate(); + } + + /** + * enableBehaviors() should work after disableBehaviors(). + * @return void + */ + public function testDisableAndEnableBehaviorsAndModels(){ + $this->setExpectedException('NewBeforeValidateBehaviorException'); + $model = new NewFormModel(); + $model->disableBehaviors(); + $model->enableBehaviors(); + $model->validate(); + } + + /** + * https://github.com/yiisoft/yii/issues/162 + */ + public function testDuplicateEventHandlers() + { + $controller = new BehaviorTestController('behaviorTest'); + + $b = new TestBehavior(); + $this->assertFalse($b->enabled); + + $b->attach($controller); + $this->assertTrue($b->enabled); + + $b->setEnabled(true); + $this->assertTrue($b->enabled); + + $controller->onTestEvent(); + $this->assertEquals(1, $controller->behaviorEventHandled); + + $b->setEnabled(false); + $this->assertFalse($b->enabled); + $controller->onTestEvent(); + $this->assertEquals(1, $controller->behaviorEventHandled); + + $b->setEnabled(true); + $this->assertTrue($b->enabled); + $controller->onTestEvent(); + $this->assertEquals(2, $controller->behaviorEventHandled); + + $b->detach($controller); + $this->assertFalse($b->enabled); + $controller->onTestEvent(); + $this->assertEquals(2, $controller->behaviorEventHandled); + + $b->setEnabled(true); + $this->assertTrue($b->enabled); + $controller->onTestEvent(); + $this->assertEquals(2, $controller->behaviorEventHandled); + } +} + diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CComponentTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CComponentTest.php new file mode 100644 index 0000000..e528ed1 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CComponentTest.php @@ -0,0 +1,346 @@ +sender->eventHandled=true; +} + +function globalEventHandler2($event) +{ + $event->sender->eventHandled=true; + $event->handled=true; +} + +class CComponentTest extends CTestCase +{ + /** + * @var NewComponent + */ + protected $component; + + public function setUp() + { + $this->component = new NewComponent(); + } + + public function tearDown() + { + $this->component = null; + } + + public function testHasProperty() + { + $this->assertTrue($this->component->hasProperty('Text'), "Component hasn't property Text"); + $this->assertTrue($this->component->hasProperty('text'), "Component hasn't property text"); + $this->assertTrue($this->component->hasProperty('Object'), "Component hasn't property Object"); + $this->assertTrue($this->component->hasProperty('object'), "Component hasn't property object"); + $this->assertFalse($this->component->hasProperty('Caption'), "Component has property Caption"); + } + + public function testCanGetProperty() + { + $this->assertTrue($this->component->canGetProperty('Text')); + $this->assertTrue($this->component->canGetProperty('text')); + $this->assertFalse($this->component->canGetProperty('Caption')); + $this->assertTrue($this->component->canGetProperty('Object')); + $this->assertTrue($this->component->canGetProperty('object')); + } + + public function testCanSetProperty() + { + $this->assertTrue($this->component->canSetProperty('Text')); + $this->assertTrue($this->component->canSetProperty('text')); + $this->assertFalse($this->component->canSetProperty('Caption')); + $this->assertFalse($this->component->canSetProperty('Object')); + $this->assertFalse($this->component->canSetProperty('object')); + } + + public function testGetProperty() + { + $this->assertSame('default', $this->component->Text); + $this->assertSame('default', $this->component->text); + $this->assertInstanceOf('NewComponent', $this->component->Object); + $this->assertInstanceOf('NewComponent', $this->component->object); + + try { + $this->component->caption; + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Property "NewComponent.caption" is not defined.', $e->getMessage()); + } + } + + public function testSetProperty() + { + $this->component->text = 'new value'; + $this->assertSame('new value', $this->component->text); + + try { + $this->component->object = new NewComponent(); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Property "NewComponent.object" is read only.', $e->getMessage()); + } + + try { + $this->component->newMember = 'new value'; + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Property "NewComponent.newMember" is not defined.', $e->getMessage()); + } + } + + public function testIsset() + { + $this->assertTrue(isset($this->component->Text)); + $this->assertFalse(empty($this->component->Text)); + $this->assertTrue(isset($this->component->object)); + } + + public function testUnset() + { + unset($this->component->Text); + $this->assertFalse(isset($this->component->Text)); + $this->assertTrue(empty($this->component->Text)); + + $this->component->Text='new text'; + $this->assertTrue(isset($this->component->Text)); + $this->assertFalse(empty($this->component->Text)); + + try { + unset($this->component->object); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Property "NewComponent.object" is read only.', $e->getMessage()); + } + } + + public function testCallMethodFromBehavior() + { + $this->component->attachBehavior('newBehavior', new NewBehavior); + $this->assertSame(2, $this->component->test()); + + try { + $this->component->otherMethod(); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('NewComponent and its behaviors do not have a method or closure named "otherMethod".', $e->getMessage()); + } + } + + public function testHasEvent() + { + $this->assertTrue($this->component->hasEvent('OnMyEvent')); + $this->assertTrue($this->component->hasEvent('onmyevent')); + $this->assertFalse($this->component->hasEvent('onYourEvent')); + } + + public function testHasEventHandler() + { + $this->assertFalse($this->component->hasEventHandler('OnMyEvent')); + $this->component->attachEventHandler('OnMyEvent','foo'); + $this->assertTrue($this->component->hasEventHandler('OnMyEvent')); + } + + public function testGetEventHandlers() + { + $list=$this->component->getEventHandlers('OnMyEvent'); + $this->assertSame($list->getCount(),0); + $this->component->attachEventHandler('OnMyEvent','foo'); + $this->assertSame($list->getCount(),1); + + try { + $this->component->getEventHandlers('YourEvent'); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Event "NewComponent.YourEvent" is not defined.', $e->getMessage()); + } + } + + public function testAttachEventHandler() + { + $this->component->attachEventHandler('OnMyEvent','foo'); + $this->assertInstanceOf('CList', $this->component->getEventHandlers('onMyEvent')); + $this->assertSame(1, $this->component->getEventHandlers('onMyEvent')->getCount()); + + try { + $this->component->attachEventHandler('onYourEvent', 'foo'); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Event "NewComponent.onYourEvent" is not defined.', $e->getMessage()); + } + } + + public function testDetachEventHandler() + { + $this->component->attachEventHandler('OnMyEvent','foo'); + $this->component->attachEventHandler('OnMyEvent',array($this->component,'myEventHandler')); + $this->assertSame($this->component->getEventHandlers('OnMyEvent')->getCount(),2); + + $this->assertTrue($this->component->detachEventHandler('OnMyEvent','foo')); + $this->assertSame($this->component->getEventHandlers('OnMyEvent')->getCount(),1); + + $this->assertFalse($this->component->detachEventHandler('OnMyEvent','foo')); + $this->assertSame($this->component->getEventHandlers('OnMyEvent')->getCount(),1); + + $this->assertTrue($this->component->detachEventHandler('OnMyEvent',array($this->component,'myEventHandler'))); + $this->assertSame($this->component->getEventHandlers('OnMyEvent')->getCount(),0); + + $this->assertFalse($this->component->detachEventHandler('OnMyEvent','foo')); + } + + /** + * https://github.com/yiisoft/yii/issues/1191 + */ + public function testAttachDetachEventHandler() + { + $this->component->attachEventHandler('OnMyEvent',array($this->component,'handler1')); + $this->component->onMyEvent(); + $this->component->attachEventHandler('OnMyEvent',array($this->component,'handler2')); + $this->component->onMyEvent(); + $this->component->attachEventHandler('OnMyEvent',array($this->component,'handler3')); + $this->component->onMyEvent(); + + $this->component->detachEventHandler('OnMyEvent',array($this->component,'handler2')); + $this->component->onMyEvent(); + + $this->component->attachEventHandler('OnMyEvent',array($this->component,'handler2')); + $this->component->onMyEvent(); + $this->component->detachEventHandler('OnMyEvent',array($this->component,'handler1')); + $this->component->onMyEvent(); + $this->component->attachEventHandler('OnMyEvent',array($this->component,'handler2')); + $this->component->onMyEvent(); + } + + + public function testRaiseEvent() + { + $this->component->attachEventHandler('OnMyEvent',array($this->component,'myEventHandler')); + $this->assertFalse($this->component->eventHandled); + $this->component->raiseEvent('OnMyEvent',new CEvent($this->component)); + $this->assertTrue($this->component->eventHandled); + + try { + $this->component->raiseEvent('OnUnknown', new CEvent($this->component)); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Event "NewComponent.onunknown" is not defined.', $e->getMessage()); + } + } + + public function testEventAccessor() + { + $component=new NewComponent; + $this->assertSame($component->onMyEvent->getCount(),0); + $component->onMyEvent='globalEventHandler'; + $component->onMyEvent=array($this->component,'myEventHandler'); + $this->assertSame($component->onMyEvent->getCount(),2); + $this->assertFalse($component->eventHandled); + $this->assertFalse($this->component->eventHandled); + $component->onMyEvent(); + $this->assertTrue($component->eventHandled); + $this->assertTrue($this->component->eventHandled); + } + + public function testStopEvent() + { + $component=new NewComponent; + $component->onMyEvent='globalEventHandler2'; + $component->onMyEvent=array($this->component,'myEventHandler'); + $component->onMyEvent(); + $this->assertTrue($component->eventHandled); + $this->assertFalse($this->component->eventHandled); + } + + public function testInvalidHandler1() + { + $this->component->onMyEvent = array(1, 2, 3); + + try { + $this->component->onMyEvent(); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Event "NewComponent.onmyevent" is attached with an invalid handler "array".', $e->getMessage()); + } + } + + public function testInvalidHandler2() + { + $this->component->onMyEvent = array($this->component, 'nullHandler'); + + try { + $this->component->onMyEvent(); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('Event "NewComponent.onmyevent" is attached with an invalid handler "nullHandler".', $e->getMessage()); + } + } + + public function testAttachingBehavior() + { + $this->component->attachBehavior('newBehavior', 'NewBehavior'); + $this->assertInstanceOf('NewBehavior', $this->component->newBehavior); + } + + public function testDetachingBehavior() + { + $behavior = new NewBehavior; + $this->component->attachBehavior('newBehavior', $behavior); + $this->assertSame($behavior, $this->component->detachBehavior('newBehavior')); + $this->assertFalse(isset($this->component->newBehavior)); + } + + public function testDetachingBehaviors() + { + $behavior = new NewBehavior; + + $this->component->attachBehavior('newBehavior', $behavior); + $this->component->detachBehaviors(); + + try { + $this->component->test(); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame('NewComponent and its behaviors do not have a method or closure named "test".', $e->getMessage()); + } + } + + public function testEnablingBehavior() + { + $behavior = new NewBehavior; + + $this->component->attachBehavior('newBehavior', $behavior); + $this->component->disableBehavior('newBehavior'); + $this->assertFalse($behavior->getEnabled()); + + $this->component->enableBehavior('newBehavior'); + $this->assertTrue($behavior->getEnabled()); + } + + public function testEnablingBehaviors() + { + $behavior = new NewBehavior; + + $this->component->attachBehavior('newBehavior', $behavior); + $this->component->disableBehaviors(); + $this->assertFalse($behavior->getEnabled()); + + $this->component->enableBehaviors(); + $this->assertTrue($behavior->getEnabled()); + } + + public function testAsa() + { + $behavior = new NewBehavior; + $this->component->attachBehavior('newBehavior', $behavior); + $this->assertSame($behavior, $this->component->asa('newBehavior')); + } + + public function testEvaluateExpression() + { + $this->assertSame('Hello world', $this->component->evaluateExpression('"Hello $who"', array('who' => 'world'))); + $this->assertSame('Hello world', $this->component->evaluateExpression(array($this->component, 'exprEvaluator'), array('who' => 'world'))); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CLogRouterTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CLogRouterTest.php new file mode 100644 index 0000000..5050348 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CLogRouterTest.php @@ -0,0 +1,54 @@ +logCollected=true; + $this->property+=count($logs); + } +} + +class CLogRouterTest extends CTestCase +{ + public function testRoutes() + { + $app=new TestApplication; + $router=new CLogRouter; + + $this->assertEquals(count($router->routes),0); + $router->routes=array( + array( + 'class'=>'MyRoute', + 'property'=>2, + ), + array( + 'class'=>'MyRoute', + 'property'=>3, + ), + ); + $router->init($app); + $this->assertEquals(count($router->routes),2); + + $route1=$router->routes[0]; + $this->assertFalse($route1->logCollected); + $this->assertEquals($route1->property,2); + $route2=$router->routes[1]; + $this->assertFalse($route2->logCollected); + $this->assertEquals($route2->property,3); + + $logger=Yii::getLogger(); + $logger->log('message1','level1','category1'); + $logger->log('message2','level2','category2'); + $logger->log('message3','level3','category3'); + + $app->onEndRequest(new CEvent($this)); + $this->assertTrue($route1->logCollected); + $this->assertTrue($route1->property>2); + $this->assertTrue($route2->logCollected); + $this->assertTrue($route2->property>3); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CLoggerTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CLoggerTest.php new file mode 100644 index 0000000..6128135 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CLoggerTest.php @@ -0,0 +1,49 @@ +log('something','debug','application.test'); + } + + public function testGetLogs() + { + $logger=new CLogger(); + $logs=array( + array('message1','debug','application.pages'), + array('message2','info','application.config'), + array('message3','info','application.pages'), + ); + foreach($logs as $log) + $logger->log($log[0],$log[1],$log[2]); + + $l=$logger->getLogs('debug'); + $this->assertTrue($logs[0]===array_slice($l[0],0,3)); + + $l=$logger->getLogs('debug , Info'); + $this->assertTrue($logs[0]===array_slice($l[0],0,3)); + $this->assertTrue($logs[1]===array_slice($l[1],0,3)); + $this->assertTrue($logs[2]===array_slice($l[2],0,3)); + + $l=$logger->getLogs('','application.config'); + $this->assertTrue($logs[1]===array_slice($l[0],0,3)); + + $l=$logger->getLogs('','application.*'); + $this->assertTrue($logs[0]===array_slice($l[0],0,3)); + $this->assertTrue($logs[1]===array_slice($l[1],0,3)); + $this->assertTrue($logs[2]===array_slice($l[2],0,3)); + + $l=$logger->getLogs('','application.config , Application.pages'); + $this->assertTrue($logs[0]===array_slice($l[0],0,3)); + $this->assertTrue($logs[1]===array_slice($l[1],0,3)); + $this->assertTrue($logs[2]===array_slice($l[2],0,3)); + + $l=$logger->getLogs('info','application.config'); + $this->assertTrue($logs[1]===array_slice($l[0],0,3)); + + $l=$logger->getLogs('info,debug','application.config'); + $this->assertTrue($logs[1]===array_slice($l[0],0,3)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CModelTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CModelTest.php new file mode 100644 index 0000000..48d5e9d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CModelTest.php @@ -0,0 +1,259 @@ +assertFalse($model->validate()); + $model->attr1=4; + $this->assertTrue($model->validate()); + $model->attr1=6; + $this->assertFalse($model->validate()); + $model->attr2=6; + $this->assertFalse($model->validate()); + $model->attr1=4; + $this->assertFalse($model->validate()); + $model->attr2=4; + $this->assertTrue($model->validate()); + } + + function testBeforeValidate(){ + $model=new NewModel; + $model->attr1=4; + $this->assertTrue($model->validate()); + + $model->onBeforeValidate = array($this, 'beforeValidate'); + $this->assertFalse($model->validate()); + } + + function beforeValidate($event){ + $event->isValid = false; + } + + function testIsAttributeRequired(){ + $model=new NewModel; + $this->assertTrue($model->isAttributeRequired('attr1')); + $this->assertFalse($model->isAttributeRequired('attr2')); + } + + function testIsAttributeSafe(){ + $model=new NewModel; + $this->assertTrue($model->isAttributeSafe('attr1')); + $this->assertFalse($model->isAttributeSafe('attr3')); + $this->assertFalse($model->isAttributeSafe('attr4')); + } + + function testGetSafeAttributeNames(){ + $model=new NewModel; + $safeAttributes = $model->getSafeAttributeNames(); + $this->assertContains('attr2', $safeAttributes); + $this->assertContains('attr1', $safeAttributes); + } + + public function testModifyValidators() + { + $model=new NewModel; + $model->attr1=2; + $model->attr2=2; + $this->assertTrue($model->validate()); + $model->validatorList->insertAt(0,CValidator::createValidator('numerical',$model,'attr1,attr2',array('min'=>3))); + $this->assertFalse($model->validate()); + $model->attr1=6; + $model->attr2=6; + $this->assertFalse($model->validate()); + $model->attr1=4; + $model->attr2=4; + $this->assertTrue($model->validate()); + $model=new NewModel; + $model->attr1=3; + $model->validatorList->add(CValidator::createValidator('required',$model,'attr2',array())); + $this->assertFalse($model->validate()); + $model->attr2=3; + $this->assertTrue($model->validate()); + } + + function testErrors(){ + $model=new NewModel; + $model->attr1=3; + $model->validatorList->add(CValidator::createValidator('required',$model,'attr2',array())); + $model->validatorList->add(CValidator::createValidator('required',$model,'attr4',array())); + $model->validate(); + + $this->assertTrue($model->hasErrors()); + $this->assertTrue($model->hasErrors('attr2')); + $this->assertFalse($model->hasErrors('attr1')); + + $model->clearErrors('attr2'); + $this->assertFalse($model->hasErrors('attr2')); + + $model->clearErrors(); + $this->assertFalse($model->hasErrors()); + } + + function testGetAttributes(){ + $model = new NewModel(); + $model->attr1 = 1; + $model->attr2 = 2; + + $attributes = $model->getAttributes(); + $this->assertEquals(1, $attributes['attr1']); + $this->assertEquals(2, $attributes['attr2']); + + $attributes = $model->getAttributes(array('attr1', 'non_existing')); + $this->assertEquals(1, $attributes['attr1']); + $this->assertNull($attributes['non_existing']); + } + + function testUnsetAttributes(){ + $model = new NewModel(); + $model->attr1 = 1; + $model->attr2 = 2; + + $model->unsetAttributes(array('attr1')); + $this->assertNull($model->attr1); + $this->assertEquals(2, $model->attr2); + + $model->unsetAttributes(); + $this->assertNull($model->attr1); + $this->assertNull($model->attr2); + } + + public function testGeneratingAttributeLabel() + { + $model = new NewModel(); + $this->assertSame('Department Name', $model->generateAttributeLabel('department_name')); + $this->assertSame('First Name', $model->generateAttributeLabel('firstName')); + $this->assertSame('Last Name', $model->generateAttributeLabel('LastName')); + } + + public function testErrorsForAllAttributes() + { + $model = new NewModel(); + $model->validate(); + $this->assertNotEmpty($model->getErrors()); + } + + public function testErrorsForSingleAttribute() + { + $model = new NewModel(); + $model->validate(); + $this->assertNotEmpty($model->getErrors('attr1')); + $this->assertEmpty($model->getErrors('attr2')); + } + + public function testAddingAnErrorToSpecifiedAttribute() + { + $model = new NewModel(); + $model->validate(); + $model->clearErrors(); + $model->addError('firstName', 'This field is required'); + $this->assertSame(1, count($model->getErrors('firstName'))); + } + + public function testAddingAnErrorToASingleAttribute() + { + $model = new NewModel(); + $model->validate(); + $model->clearErrors(); + $model->addErrors(array('firstName' => 'This field is required')); + $this->assertSame(1, count($model->getErrors('firstName'))); + } + + public function testAddingAnErrorToMultipleAttributes() + { + $model = new NewModel(); + $model->validate(); + $model->clearErrors(); + $model->addErrors(array( + 'firstName' => array('This attribute is required'), + 'LastName' => array('This field is required'), + )); + $this->assertSame(1, count($model->getErrors('firstName'))); + $this->assertSame(1, count($model->getErrors('LastName'))); + } + + public function testAddingMultipleErrorsToASingleAttribute() + { + $model = new NewModel(); + $model->validate(); + $model->clearErrors(); + $model->addErrors(array('firstName' => array( + 'This attribute is required', + 'This field is required', + ))); + $this->assertSame(2, count($model->getErrors('firstName'))); + } + + public function testAddingMultipleErrorsToMultipleAttributes() + { + $model = new NewModel(); + $model->validate(); + $model->clearErrors(); + $model->addErrors(array( + 'firstName' => array( + 'This attribute is required', + 'This field is required', + ), + 'LastName' => array( + 'This attribute is required', + 'This field is required', + ), + )); + $this->assertSame(2, count($model->getErrors('firstName'))); + $this->assertSame(2, count($model->getErrors('LastName'))); + } + + public function testFirstErrorMessageForInvalidAttribute() + { + $model = new NewModel(); + $model->validate(); + $model->clearErrors(); + $model->addErrors(array( + 'attr1' => array( + 'This attribute is required.', + 'This field is required.', + ), + )); + $this->assertSame('This attribute is required.', $model->getError('attr1')); + } + + public function testNoErrorMessageForValidAttribute() + { + $model = new NewModel(); + $model->validate(); + $this->assertNull($model->getError('attr2')); + } + + public function testModelWithInvalidRules() + { + $model = new InvalidModel(); + try { + $this->assertFalse($model->validate()); + } catch (Exception $e) { + $this->assertInstanceOf('CException', $e); + $this->assertSame( + 'InvalidModel has an invalid validation rule. '. + 'The rule must specify attributes to be validated and the validator name.', + $e->getMessage()); + } + } + + /** + * @see https://github.com/yiisoft/yii/pull/2259 + */ + public function testAddValidator() + { + $model=new NewModel(); + $scenario='test'; + $model->scenario=$scenario; + $model->addValidator('required','firstName',array('on'=>$scenario)); + $this->assertTrue($model->isAttributeRequired('firstName')); + $validators = $model->getValidatorList(); + //gets last validator in the list + $validator = $validators->itemAt($validators->count()-1); + $this->assertInstanceOf('CRequiredValidator',$validator); + $this->assertSame($validator->attributes[0],'firstName'); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CModuleTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CModuleTest.php new file mode 100644 index 0000000..51b1177 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CModuleTest.php @@ -0,0 +1,123 @@ +parent = new NewModule('root',NULL); + $this->mod = new NewModule('foo',$this->parent); + $this->d = dirname(__FILE__); + } + public function tearDown() { + unset($this->parent); + unset($this->mod); + } + public function testGetId() { + $this->assertEquals('foo',$this->mod->getId()); + } + public function testSetId() { + $this->mod->setId('bar'); + $this->assertEquals('bar',$this->mod->getId()); + } + public function testSetBasePath() { + $d = dirname($this->d.'/..'); + $this->mod->setBasePath($d); + $this->assertEquals($d,$this->mod->getBasePath()); + } + public function testGetBasePath() { + $this->assertEquals($this->d,$this->mod->getBasePath()); + } + public function testGetParams() { + $expected = new CAttributeCollection; + $expected->caseSensitive = TRUE; + $this->assertEquals($expected,$this->mod->getParams()); + } + public function testSetParams() { + $expected = array('foo' => 'bar'); + $this->mod->setParams($expected); + $this->assertEquals($expected,$this->mod->getParams()->toArray()); + } + public function testGetModulePath() { + $expected = $this->d.DIRECTORY_SEPARATOR.'modules'; + $this->assertEquals($expected,$this->mod->getModulePath()); + } + public function testSetModulePath() { + $this->mod->setModulePath($this->d); + $this->assertEquals($this->d,$this->mod->getModulePath()); + } + public function testGetParentModule() { + $this->assertSame($this->parent,$this->mod->getParentModule()); + } + /** + * @depends testGetId + */ + public function testGetModule() { + $p = $this->parent; + $p->setModulePath($this->d); + $p->setModules(array('foo' => array('class' => 'NewModule'))); + $this->assertEquals('root/foo',$p->getModule('foo')->getId()); + } + public function testGetModules() { + $p = $this->parent; + $p->setModulePath($this->d); + $expected = array('foo' => array('class' => 'NewModule'),'bar'); + $p->setModules($expected); + $expected['bar'] = array('class' => 'bar.BarModule'); + unset($expected[0]); + $this->assertEquals($expected,$p->getModules()); + } + public function testGetComponents() { + $c = new NewApplicationComponent; + $this->mod->setComponent('foo',$c); + $this->assertSame(array('foo' => $c),$this->mod->getComponents()); + } + public function testSetComponents() { + $expected = array('foo' => new NewApplicationComponent); + $this->mod->setComponents($expected); + $this->assertSame($expected,$this->mod->getComponents()); + } + public function testSetComponentsViaConfig() { + $this->mod = new NewModule('foo',$this->parent,array( + 'components' => array( + 'bar' => array('class' => 'NewApplicationComponent'), + ), + )); + $this->assertEquals('hello world',$this->mod->bar->getText('hello world')); + $this->mod->setComponents(array( + 'bar' => array('text' => 'test'), + )); + $this->assertEquals('test',$this->mod->bar->getText()); + $this->mod->setComponent('bar',null); + $this->assertEquals('test',$this->mod->bar->getText()); + $this->mod->setComponents(array( + 'bar' => array('class' => 'NewApplicationComponent'), + )); + $this->assertEquals('test',$this->mod->bar->getText()); + $this->mod->setComponents(array( + 'bar' => array('class' => 'AnotherNewApplicationComponent'), + )); + $this->assertEquals('new',$this->mod->bar->getText()); + $this->mod->setComponent('bar',null); + $this->assertEquals('new',$this->mod->bar->getText()); + $this->mod->setComponent('bar',null); + $this->mod->setComponents(array( + 'bar' => array( + 'class' => 'NewApplicationComponent', + 'text' => 'test', + ), + )); + $this->mod->setComponents(array( + 'bar' => array('class' => 'AnotherNewApplicationComponent'), + )); + $this->assertEquals('new',$this->mod->bar->getText()); + } + public function testSetAliases() { + $this->mod->setAliases(array('modules' => $this->d)); + $this->assertEquals($this->d,Yii::getPathOfAlias('modules')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CPropertyValueTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CPropertyValueTest.php new file mode 100644 index 0000000..960caa3 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CPropertyValueTest.php @@ -0,0 +1,152 @@ +$entry) + $this->assertTrue(CPropertyValue::ensureBoolean($entry[0])===$entry[1], + "Comparison $index: {$this->varToString($entry[0])}=={$this->varToString($entry[1])}"); + } + + public function testEnsureString() + { + $entries=array + ( + array('',''), + array('abc','abc'), + array(null,''), + array(0,'0'), + array(1,'1'), + array(-1.1,'-1.1'), + array(true,'true'), + array(false,'false'), + ); + + if(version_compare(PHP_VERSION, '5.4.0', '<')) + { + $entries = array_merge($entries, array( + array(array(),'Array'), + array(array(0),'Array'), + )); + } + + foreach($entries as $index=>$entry) + $this->assertTrue(CPropertyValue::ensureString($entry[0])===$entry[1], + "Comparison $index: {$this->varToString($entry[0])}=={$this->varToString($entry[1])}"); + } + + public function testEnsureInteger() + { + $entries=array + ( + array(123,123), + array(1.23,1), + array(null,0), + array('',0), + array('abc',0), + array('123',123), + array('1.23',1), + array(' 1.23',1), + array(' 1.23abc',1), + array('abc1.23abc',0), + array(true,1), + array(false,0), + array(array(),0), + array(array(0),1), + ); + foreach($entries as $index=>$entry) + $this->assertTrue(CPropertyValue::ensureInteger($entry[0])===$entry[1], + "Comparison $index: {$this->varToString($entry[0])}=={$this->varToString($entry[1])}"); + } + + public function testEnsureFloat() + { + $entries=array + ( + array(123,123.0), + array(1.23,1.23), + array(null,0.0), + array('',0.0), + array('abc',0.0), + array('123',123.0), + array('1.23',1.23), + array(' 1.23',1.23), + array(' 1.23abc',1.23), + array('abc1.23abc',0.0), + array(true,1.0), + array(false,0.0), + array(array(),0.0), + array(array(0),1.0), + ); + foreach($entries as $index=>$entry) + $this->assertTrue(CPropertyValue::ensureFloat($entry[0])===$entry[1], + "Comparison $index: {$this->varToString($entry[0])}=={$this->varToString($entry[1])}"); + } + + public function testEnsureArray() + { + $entries=array + ( + array(123,array(123)), + array(null,array()), + array('',array()), + array('abc',array('abc')), + array('(1,2)',array(1,2)), + array('("key"=>"value",2=>3)',array("key"=>"value",2=>3)), + array(true,array(true)), + array(array(),array()), + array(array(0),array(0)), + ); + foreach($entries as $index=>$entry) + $this->assertTrue(CPropertyValue::ensureArray($entry[0])===$entry[1], + "Comparison $index: {$this->varToString($entry[0])}=={$this->varToString($entry[1])}"); + } + + private function varToString($var) + { + if(is_array($var)) + return 'Array'; + return (string)$var; + } + + public function testEnsureObject() + { + $obj=new stdClass; + $this->assertTrue(CPropertyValue::ensureObject($obj)===$obj); + } + + public function testEnsureEnum() + { + $this->assertTrue(CPropertyValue::ensureEnum('Left','TextAlign')==='Left'); + $this->setExpectedException('CException'); + $this->assertTrue(CPropertyValue::ensureEnum('left','TextAlign')==='Left'); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CSecurityManagerTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CSecurityManagerTest.php new file mode 100644 index 0000000..2eb7983 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CSecurityManagerTest.php @@ -0,0 +1,123 @@ +reset(); + } + + public function testValidationKey() + { + $sm=new CSecurityManager; + $key='123456'; + $sm->validationKey=$key; + $this->assertEquals($key,$sm->validationKey); + + $app=new TestApplication; + $key=$app->securityManager->validationKey; + $app->saveGlobalState(); + $app2=new TestApplication; + $this->assertEquals($app2->securityManager->validationKey,$key); + } + + public function testEncryptionKey() + { + $sm=new CSecurityManager; + $key='123456'; + $sm->encryptionKey=$key; + $this->assertEquals($key,$sm->encryptionKey); + + $app=new TestApplication; + $key=$app->securityManager->encryptionKey; + $app->saveGlobalState(); + $app2=new TestApplication; + $this->assertEquals($app2->securityManager->encryptionKey,$key); + } + + public function testValidation() + { + $sm=new CSecurityManager; + $mode='SHA1'; + $sm->hashAlgorithm=$mode; + $this->assertEquals($mode,$sm->hashAlgorithm); + } + + public function testValidateData() + { + $sm=new CSecurityManager; + $sm->validationKey='123456'; + $sm->hashAlgorithm='SHA1'; + $data='this is raw data'; + $hashedData=$sm->hashData($data); + $this->assertEquals($data,$sm->validateData($hashedData)); + $hashedData[3]='c'; // tamper the data + $this->assertTrue($sm->validateData($hashedData)===false); + + $sm->hashAlgorithm='MD5'; + $data='this is raw data'; + $hashedData=$sm->hashData($data); + $this->assertEquals($data,$sm->validateData($hashedData)); + $hashedData[3]='c'; // tamper the data + $this->assertTrue($sm->validateData($hashedData)===false); + } + + public function testEncryptData() + { + if(!extension_loaded('mcrypt')) + $this->markTestSkipped('mcrypt extension is required to test encrypt feature.'); + $sm=new CSecurityManager; + $sm->encryptionKey='123456'; + $data='this is raw data'; + $encryptedData=$sm->encrypt($data); + $this->assertTrue($data!==$encryptedData); + $data2=$sm->decrypt($encryptedData); + $this->assertEquals($data,$data2); + } + + public function providerComputeHMAC() + { + return array( + array( + '7638cbf5b66f451a5dab87fa26f45025fa661f82', + 'data1', + '123456', + 'sha1', + ), + array( + '7e9a30dd2e3c568499a0786ca776d29ee9fb00f6', + 'data2', + '123456', + 'SHA1', + ), + array( + '289beb389d31d327eb87fd8f102970d1', + 'data1', + '123456', + 'md5', + ), + array( + '4fb0dd0081ce2681f479d42ec8db5537', + 'data2', + '123456', + 'MD5', + ), + ); + } + + /** + * @dataProvider providerComputeHMAC + */ + public function testComputeHMAC($assertion,$data,$key,$hashAlgorithm) + { + $sm1=new CSecurityManager; + $sm1->validationKey=$key; + $sm1->hashAlgorithm=$hashAlgorithm; + $this->assertEquals($assertion,$sm1->computeHMAC($data)); + + $sm2=new CSecurityManager; + $this->assertEquals($assertion,$sm2->computeHMAC($data,$key,$hashAlgorithm)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CStatePersisterTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CStatePersisterTest.php new file mode 100644 index 0000000..469fd5e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/CStatePersisterTest.php @@ -0,0 +1,33 @@ +reset(); + } + + public function testLoadSave() + { + $app=new TestApplication; + $sp=$app->statePersister; + $data=array('123','456','a'=>443); + $sp->save($data); + $this->assertEquals($sp->load(),$data); + // TODO: test with cache on + } + + public function testStateFile() + { + $sp=new CStatePersister; + $file=dirname(__FILE__).DIRECTORY_SEPARATOR.'state.bin'; + $sp->stateFile=$file; + $this->assertEquals($sp->stateFile,$file); + + $sp->stateFile=dirname(__FILE__).'/unknown/state.bin'; + $this->setExpectedException('CException'); + $sp->init(); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewApplicationComponent.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewApplicationComponent.php new file mode 100644 index 0000000..06923cb --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewApplicationComponent.php @@ -0,0 +1,13 @@ +_text; + } + return $text; + } + public function setText($val) { + $this->_text = $val; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewBeforeValidateBehavior.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewBeforeValidateBehavior.php new file mode 100644 index 0000000..52307c8 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewBeforeValidateBehavior.php @@ -0,0 +1,8 @@ +owner->behaviorCalled=true; + return 2; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewComponent.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewComponent.php new file mode 100644 index 0000000..5b78c5f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewComponent.php @@ -0,0 +1,46 @@ +_text; + } + + public function setText($value) + { + $this->_text=$value; + } + + public function getObject() + { + if(!$this->_object) + { + $this->_object=new NewComponent; + $this->_object->_text='object text'; + } + return $this->_object; + } + + public function onMyEvent() + { + $this->raiseEvent('OnMyEvent',new CEvent($this)); + } + + public function myEventHandler($event) + { + $this->eventHandled=true; + } + + public function exprEvaluator($p1,$comp) { + return "Hello $p1"; + } + + public function handler1() {} + public function handler2() {} + public function handler3() {} +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewFormModel.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewFormModel.php new file mode 100644 index 0000000..788836d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewFormModel.php @@ -0,0 +1,10 @@ + array( + 'class' => 'NewBeforeValidateBehavior', + ), + ); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewModel.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewModel.php new file mode 100644 index 0000000..43ab984 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewModel.php @@ -0,0 +1,44 @@ +5), + array('attr1','required'), + array('attr3', 'unsafe'), + ); + } + + public function attributeNames() + { + return array('attr1','attr2'); + } + +} + +class InvalidModel extends CModel +{ + public $username; + + public function rules() + { + return array( + array('username'), + ); + } + + public function attributeNames() + { + return array('username'); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewModule.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewModule.php new file mode 100644 index 0000000..9803140 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/base/NewModule.php @@ -0,0 +1,4 @@ + 'handleTest', + ); + } + + public function handleTest($event) + { + if (!($event instanceof CEvent)) { + throw new CException('event has to be instance of CEvent'); + } + $this->owner->behaviorEventHandled++; + } + } \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CCacheDependencyTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CCacheDependencyTest.php new file mode 100644 index 0000000..2e7dbf6 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CCacheDependencyTest.php @@ -0,0 +1,67 @@ +_cacheDependentData = $cacheDependentData; + } + + public function getCacheDependentData() + { + return $this->_cacheDependentData; + } + + public function testReuseDependentData() + { + MockCacheDependency::$generateDependentDataCallback=array($this,'getCacheDependentData'); + $dependency1=new MockCacheDependency(); + $dependency1->reuseDependentData = true; + $dependency2=new MockCacheDependency(); + $dependency2->reuseDependentData = true; + + CCacheDependency::resetReusableData(); + $this->setCacheDependentData('start'); + $dependency1->evaluateDependency(); + $dependency2->evaluateDependency(); + $this->assertFalse($dependency1->getHasChanged(),'Initial dependency1 changed!'); + $this->assertFalse($dependency2->getHasChanged(),'Initial dependency2 changed!'); + $this->assertEquals(1,MockCacheDependency::$generateDependentDataCalled,'Extra invokations of "generateDependentData()"!'); + + // New request: + CCacheDependency::resetReusableData(); + MockCacheDependency::$generateDependentDataCalled=0; + $this->assertFalse($dependency1->getHasChanged(),'Dependency1 changed for new request!'); + $this->assertFalse($dependency2->getHasChanged(),'Dependency2 changed for new request!'); + $this->assertEquals(1,MockCacheDependency::$generateDependentDataCalled,'Extra invokations of "generateDependentData()"!'); + + // New request: + CCacheDependency::resetReusableData(); + MockCacheDependency::$generateDependentDataCalled=0; + $this->setCacheDependentData('change1'); + $this->assertTrue($dependency1->getHasChanged(),'Dependency1 is not changed after source change!'); + $dependency1->evaluateDependency(); + + // New request: + CCacheDependency::resetReusableData(); + MockCacheDependency::$generateDependentDataCalled=0; + $this->assertFalse($dependency1->getHasChanged(),'Dependency1 has been changed!'); + $this->assertTrue($dependency2->getHasChanged(),'Dependency2 has not been changed!'); + $this->assertEquals(1,MockCacheDependency::$generateDependentDataCalled,'Extra invokations of "generateDependentData()"!'); + } +} + +class MockCacheDependency extends CCacheDependency +{ + public static $generateDependentDataCallback; + public static $generateDependentDataCalled = 0; + + public function generateDependentData() + { + self::$generateDependentDataCalled++; + return call_user_func(self::$generateDependentDataCallback); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CDbCacheTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CDbCacheTest.php new file mode 100644 index 0000000..655edde --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CDbCacheTest.php @@ -0,0 +1,197 @@ +getRuntimePath().'/CDbCacheTest_database.db'); + +if(!defined('DBCACHE_TEST_DB')) + define('DBCACHE_TEST_DB','sqlite:'.DBCACHE_TEST_DBFILE); + + +class CDbCacheTest extends CTestCase +{ + private $_config1=array( + 'id'=>'testApp', + 'components'=>array( + 'cache'=>array( + 'class'=>'CDbCache', + ), + ), + ); + private $_config2=array( + 'id'=>'testApp', + 'components'=>array( + 'db'=>array( + 'connectionString'=>DBCACHE_TEST_DB, + ), + 'cache'=>array( + 'class'=>'system.caching.CDbCache', + 'connectionID'=>'db', + ), + ), + ); + + public function setUp() + { + if(!extension_loaded('pdo') || !extension_loaded('pdo_sqlite')) + $this->markTestSkipped('PDO and SQLite extensions are required.'); + } + + public function testKeyPrefix() + { + $cache=new CDbCache; + $this->assertEquals($cache->keyPrefix,''); + $cache->keyPrefix='key'; + $this->assertEquals($cache->keyPrefix,'key'); + + $app=new TestApplication($this->_config1); + $app->reset(); + $this->assertTrue($app->cache instanceof CDbCache); + $this->assertEquals($app->cache->keyPrefix,$app->id); + } + + public function testGetAndSet() + { + $app=new TestApplication($this->_config1); + $app->reset(); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key='data1'; + + $this->assertFalse($cache->get($key)); + $cache->set($key,$data); + $this->assertTrue($cache->get($key)===$data); + + $app2=new TestApplication($this->_config1); + $this->assertTrue($app2->cache->get($key)===$data); + } + + public function testMGet() + { + $app=new TestApplication($this->_config1); + $app->reset(); + $cache=$app->cache; + + $key1='multidata1'; + $data1='abc'; + $key2='multidata2'; + $data2=34; + + $this->assertEquals($cache->mget(array($key1,$key2)), array($key1=>false,$key2=>false)); + $cache->set($key1,$data1); + $cache->set($key2,$data2); + $this->assertEquals($cache->mget(array($key1,$key2)), array($key1=>$data1,$key2=>$data2)); + $app2=new TestApplication($this->_config1); + $this->assertEquals($app2->cache->mget(array($key1,$key2)), array($key1=>$data1,$key2=>$data2)); + } + + public function testArrayAccess() + { + $app=new TestApplication($this->_config1); + $app->reset(); + $cache=$app->cache; + $data=array('abc'=>1,2=>'def'); + $key='data2'; + $cache[$key]=$data; + $this->assertTrue($cache->get($key)===$data); + $this->assertTrue($cache[$key]===$data); + unset($cache[$key]); + $this->assertFalse($cache[$key]); + } + + public function testExpire() + { + $app=new TestApplication($this->_config1); + $app->reset(); + $cache=$app->cache; + $data=array('abc'=>1,2=>'def'); + $key='data3'; + $cache->set($key,$data,2); + $this->assertTrue($cache->get($key)===$data); + sleep(4); + $app2=new TestApplication($this->_config1); + $this->assertFalse($app2->cache->get($key)); + } + + public function testUseDbConnection() + { + @unlink(DBCACHE_TEST_DBFILE); + $app=new TestApplication($this->_config2); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key='data4'; + $this->assertFalse($cache->get($key)); + $cache->set($key,$data); + $this->assertTrue($cache->get($key)===$data); + + $app2=new TestApplication($this->_config2); + $this->assertTrue($app2->cache->get($key)===$data); + } + + public function testDependency() + { + @unlink(DBCACHE_TEST_DBFILE); + $app=new TestApplication($this->_config2); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key='data5'; + + $cache->set($key,$data,0,new CFileCacheDependency(__FILE__)); + $this->assertTrue($cache->get($key)===$data); + $app=new TestApplication($this->_config2); + $this->assertTrue($app->cache->get($key)===$data); + + $key2='data6'; + $cache->set($key2,$data,0,new CFileCacheDependency(DBCACHE_TEST_DBFILE)); + sleep(2); // sleep to ensure timestamp is changed for the db file + $cache->set('data7',$data); + $app=new TestApplication($this->_config2); + $this->assertFalse($app->cache->get($key2)); + } + + public function testAdd() + { + @unlink(DBCACHE_TEST_DBFILE); + $app=new TestApplication($this->_config2); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key='data8'; + + $cache->set($key,$data); + $this->assertTrue($cache->set($key,$data)); + $this->assertFalse($cache->add($key,$data)); + $this->assertTrue($cache->add('data9',$data)); + } + + public function testDelete() + { + @unlink(DBCACHE_TEST_DBFILE); + $app=new TestApplication($this->_config2); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key='data10'; + $cache->set($key,$data); + $cache->delete($key); + $this->assertFalse($cache->get($key)); + } + + public function testFlush() + { + @unlink(DBCACHE_TEST_DBFILE); + $app=new TestApplication($this->_config2); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key1='data11'; + $key2='data12'; + $cache->set($key1,$data); + $cache->set($key2,$data); + $cache->flush(); + $this->assertFalse($cache->get($key1)); + $this->assertFalse($cache->get($key2)); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CDirectoryCacheDependencyTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CDirectoryCacheDependencyTest.php new file mode 100644 index 0000000..9dfdcbf --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CDirectoryCacheDependencyTest.php @@ -0,0 +1,70 @@ +reset(); + $this->testDir1 = Yii::app()->getRuntimePath().'/CDirectoryCacheDependencyTest_temp1'; + @mkdir($this->testDir1); + $this->testDir2 = Yii::app()->getRuntimePath().'/CDirectoryCacheDependencyTest_temp2'; + } + + public function testDirectoryName() + { + $directory=realpath($this->testDir1); + $dependency=new CDirectoryCacheDependency($directory); + $this->assertEquals($dependency->directory,$directory); + + $this->setExpectedException('CException'); + $dependency=new CDirectoryCacheDependency($this->testDir2); + $dependency->evaluateDependency(); + } + + public function testRecursiveLevel() + { + $dependency=new CDirectoryCacheDependency($this->testDir1); + $this->assertEquals($dependency->recursiveLevel,-1); + $dependency->recursiveLevel=5; + $this->assertEquals($dependency->recursiveLevel,5); + } + + public function testHasChanged() + { + $tempFile=$this->testDir1.'/foo.txt'; + @unlink($tempFile); + $fw=fopen($tempFile,"w"); + fwrite($fw,"test"); + fclose($fw); + clearstatcache(); + + $dependency=new CDirectoryCacheDependency(dirname($tempFile)); + $dependency->evaluateDependency(); + $str=serialize($dependency); + + // test directory not changed + sleep(2); + $dependency=unserialize($str); + $this->assertFalse($dependency->hasChanged); + + // change file + $fw=fopen($tempFile,"w"); + fwrite($fw,"test again"); + fclose($fw); + clearstatcache(); + + // test file changed + sleep(2); + $dependency->evaluateDependency(); + $dependency=unserialize($str); + $this->assertTrue($dependency->hasChanged); + + @unlink($tempFile); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CFileCacheDependencyTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CFileCacheDependencyTest.php new file mode 100644 index 0000000..c21581f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CFileCacheDependencyTest.php @@ -0,0 +1,51 @@ +assertEquals($dependency->fileName,__FILE__); + $dependency->evaluateDependency(); + $this->assertEquals($dependency->dependentData,filemtime(__FILE__)); + + $dependency=new CFileCacheDependency(dirname(__FILE__).'/foo.txt'); + $dependency->evaluateDependency(); + $this->assertFalse($dependency->dependentData); + } + + public function testHasChanged() + { + $tempFile=Yii::app()->getRuntimePath().'/CFileCacheDependencyTest_foo.txt'; + @unlink($tempFile); + $fw=fopen($tempFile,"w"); + fwrite($fw,"test"); + fclose($fw); + clearstatcache(); + + $dependency=new CFileCacheDependency($tempFile); + $dependency->evaluateDependency(); + $str=serialize($dependency); + + // test file not changed + sleep(2); + $dependency=unserialize($str); + $this->assertFalse($dependency->hasChanged); + + // change file + $fw=fopen($tempFile,"w"); + fwrite($fw,"test again"); + fclose($fw); + clearstatcache(); + + // test file changed + sleep(2); + $dependency->evaluateDependency(); + $dependency=unserialize($str); + $this->assertTrue($dependency->hasChanged); + + @unlink($tempFile); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CFileCacheTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CFileCacheTest.php new file mode 100644 index 0000000..67d8bbf --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CFileCacheTest.php @@ -0,0 +1,53 @@ +'testApp', + 'components'=>array( + 'cache'=>array('class'=>'CFileCache'), + ), + )); + $app->reset(); + $cache=$app->cache; + + $cache->set('testKey1','testValue1',2); + $files=glob(Yii::getPathOfAlias('application.runtime.cache').'/*.bin'); + $this->assertEquals(time()+2,filemtime($files[0])); + + $cache->set('testKey2','testValue2',2); + sleep(1); + $this->assertEquals('testValue2',$cache->get('testKey2')); + + $cache->set('testKey3','testValue3',2); + sleep(3); + $this->assertEquals(false,$cache->get('testKey2')); + + + $app=new TestApplication(array( + 'id'=>'testApp', + 'components'=>array( + 'cache'=>array('class'=>'CFileCache','embedExpiry'=>true), + ), + )); + $app->reset(); + $cache=$app->cache; + + $cache->set('testKey4','testValue4',2); + $files=glob(Yii::getPathOfAlias('application.runtime.cache').'/*.bin'); + $this->assertEquals(time(),filemtime($files[0])); + + $cache->set('testKey5','testValue5',2); + sleep(1); + $this->assertEquals('testValue5',$cache->get('testKey5')); + + $cache->set('testKey6','testValue6',2); + sleep(3); + $this->assertEquals(false,$cache->get('testKey6')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CMemCacheTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CMemCacheTest.php new file mode 100644 index 0000000..af40d12 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CMemCacheTest.php @@ -0,0 +1,165 @@ +'testApp', + 'components'=>array( + 'cache'=>array( + 'class'=>'CMemCache', + 'servers'=>array( + array('host'=>MEMCACHE_TEST_HOST, 'port'=>MEMCACHE_TEST_PORT, 'weight'=>100), + ), + ), + ), + + ); + + public function setUp() + { + if(!extension_loaded('memcache') && !extension_loaded('memcached')) + $this->markTestSkipped('Memcache or memcached extensions are required.'); + } + + public function testMget() + { + $app=new TestApplication($this->_config); + $app->reset(); + $cache=$app->cache; + + $data1=array('abc'=>1,2=>'def'); + $key1='data1'; + $data2=array('xyz'=>3,4=>'whn'); + $key2='data2'; + + $cache->delete($key1); + $cache->delete($key2); + + $this->assertFalse($cache->get($key1)); + $this->assertFalse($cache->get($key2)); + + $cache->set($key1,$data1); + $cache->set($key2,$data2); + $this->assertTrue($cache->get($key1)===$data1); + $this->assertTrue($cache->get($key2)===$data2); + + $mgetResult = $cache->mget(array($key1, $key2)); + $this->assertTrue(is_array($mgetResult)); + $this->assertEquals($mgetResult[$key1],$data1); + $this->assertEquals($mgetResult[$key2],$data2); + + $cache->delete($key2); + $mgetResult = $cache->mget(array($key1, $key2)); + $this->assertTrue(is_array($mgetResult)); + $this->assertEquals($mgetResult[$key1],$data1); + $this->assertFalse($mgetResult[$key2]); // data2 is removed from cache + + $cache->delete($key1); + $mgetResult = $cache->mget(array($key1, $key2)); + $this->assertTrue(is_array($mgetResult)); + $this->assertFalse($mgetResult[$key1]); // data1 is removed from cache + $this->assertFalse($mgetResult[$key2]); // data2 is removed from cache + } + + public function testKeyPrefix() + { + $cache=new CMemCache; + $this->assertEquals($cache->keyPrefix,''); + $cache->keyPrefix='key'; + $this->assertEquals($cache->keyPrefix,'key'); + + $app=new TestApplication($this->_config); + $app->reset(); + $this->assertTrue($app->cache instanceof CMemCache); + $this->assertEquals($app->cache->keyPrefix,$app->id); + } + + public function testGetAndSet() + { + $app=new TestApplication($this->_config); + $app->reset(); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key='data1'; + $cache->delete($key); + + $this->assertFalse($cache->get($key)); + $cache->set($key,$data); + $this->assertTrue($cache->get($key)===$data); + + $app2=new TestApplication($this->_config); + $this->assertTrue($app2->cache->get($key)===$data); + } + + public function testArrayAccess() + { + $app=new TestApplication($this->_config); + $app->reset(); + $cache=$app->cache; + $data=array('abc'=>1,2=>'def'); + $key='data2'; + $cache[$key]=$data; + $this->assertTrue($cache->get($key)===$data); + $this->assertTrue($cache[$key]===$data); + unset($cache[$key]); + $this->assertFalse($cache[$key]); + } + + public function testExpire2() + { + $app=new TestApplication($this->_config); + $app->reset(); + $cache=$app->cache; + $data=array('xyz'=>3,4=>'mnp'); + $key='data3_2'; + $cache->set($key,$data,20); + $this->assertTrue($cache->get($key)===$data); + sleep(2); + $app2=new TestApplication($this->_config); + $this->assertEquals($data,$app2->cache->get($key)); + } + + public function testDelete() + { + $app=new TestApplication($this->_config); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key='data10'; + $cache->set($key,$data); + $cache->delete($key); + $this->assertFalse($cache->get($key)); + } + + public function testBigExpireValues() + { + $app=new TestApplication($this->_config); + $cache=$app->cache; + + $cache->set('key_1','value_1',60*60*24*30-10); + $cache->set('key_2','value_2',60*60*24*30-2); + $cache->set('key_3','value_3',60*60*24*30-1); + $cache->set('key_4','value_4',60*60*24*30); + $cache->set('key_5','value_5',60*60*24*30+1); + $cache->set('key_6','value_6',60*60*24*30+2); + $cache->set('key_7','value_7',60*60*24*30+10); + + sleep(4); + + $this->assertEquals('value_1',$cache->get('key_1')); + $this->assertEquals('value_2',$cache->get('key_2')); + $this->assertEquals('value_3',$cache->get('key_3')); + $this->assertEquals('value_4',$cache->get('key_4')); + $this->assertEquals('value_5',$cache->get('key_5')); + $this->assertEquals('value_6',$cache->get('key_6')); + $this->assertEquals('value_7',$cache->get('key_7')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CRedisCacheTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CRedisCacheTest.php new file mode 100644 index 0000000..21cfb66 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/caching/CRedisCacheTest.php @@ -0,0 +1,132 @@ + 'CRedisCache', + 'hostname' => 'localhost', + 'port' => 6379, + 'database' => 0, + ); + + protected function getApplication() + { + $app=new TestApplication(array( + 'id' => 'testapp', + 'components'=>array( + 'cache' => $this->config + ) + )); + $app->cache->flush(); + return $app; + } + + public function setUp() + { + $dsn = $this->config['hostname'] . ':' .$this->config['port']; + if(!@stream_socket_client($dsn, $errorNumber, $errorDescription, 0.5)) { + $this->markTestSkipped('No redis server running at ' . $dsn .' : ' . $errorNumber . ' - ' . $errorDescription); + } + } + + public function testKeyPrefix() + { + $cache=new CRedisCache; + $this->assertEquals($cache->keyPrefix,''); + $cache->keyPrefix='key'; + $this->assertEquals($cache->keyPrefix,'key'); + + $app=$this->getApplication(); + $this->assertTrue($app->cache instanceof CRedisCache); + $this->assertEquals($app->id,$app->cache->keyPrefix); + } + + public function testGetAndSet() + { + $app=$this->getApplication(); + $cache=$app->cache; + + $data=array('abc'=>1,2=>'def'); + $key='data1'; + + $this->assertFalse($cache->get($key)); + $cache->set($key,$data); + $this->assertTrue($cache->get($key)===$data); + } + + public function testMGet() + { + $app=$this->getApplication(); + $cache=$app->cache; + + $key1='multidata1'; + $data1='abc'; + $key2='multidata2'; + $data2=34; + + $this->assertEquals($cache->mget(array($key1,$key2)), array($key1=>false,$key2=>false)); + $cache->set($key1,$data1); + $cache->set($key2,$data2); + $this->assertEquals($cache->mget(array($key1,$key2)), array($key1=>$data1,$key2=>$data2)); + } + + public function testArrayAccess() + { + $app=$this->getApplication(); + $cache=$app->cache; + $data=array('abc'=>1,2=>'def'); + $key='data2'; + $cache[$key]=$data; + $this->assertTrue($cache->get($key)===$data); + $this->assertTrue($cache[$key]===$data); + unset($cache[$key]); + $this->assertFalse($cache[$key]); + } + + public function testExpire() + { + $app=$this->getApplication(); + $cache=$app->cache; + $data=array('abc'=>1,2=>'def'); + $key='data3'; + $cache->set($key,$data,2); + $this->assertTrue($cache->get($key)===$data); + sleep(1); + $this->assertTrue($cache->get($key)===$data); + sleep(2); + $this->assertFalse($cache->get($key)); + } + + public function testAdd() + { + $cache = $this->getApplication()->cache; + $this->assertTrue($cache->set('number_test', 42)); + + // should not change existing keys + $this->assertFalse($cache->add('number_test', 13)); + $this->assertEquals(42, $cache->get('number_test')); + + // should store data if it's not there yet + $this->assertFalse($cache->get('add_test')); + $this->assertTrue($cache->add('add_test', 13)); + $this->assertEquals(13, $cache->get('add_test')); + } + + public function testDelete() + { + $cache = $this->getApplication()->cache; + $this->assertTrue($cache->set('number_test', 'testvalue')); + + $this->assertNotNull($cache->get('number_test')); + $this->assertTrue($cache->delete('number_test')); + $this->assertFalse($cache->get('number_test')); + } + + public function testFlush() + { + $cache = $this->getApplication()->cache; + $this->assertTrue($cache->set('number_test', 'testvalue')); + $this->assertTrue($cache->flush()); + $this->assertFalse($cache->get('number_test')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/cli/commands/MessageCommandTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/cli/commands/MessageCommandTest.php new file mode 100644 index 0000000..3e4e53e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/cli/commands/MessageCommandTest.php @@ -0,0 +1,357 @@ +sourcePath=Yii::getPathOfAlias('application.runtime.test_source'); + $this->createDir($this->sourcePath); + $this->messagePath=Yii::getPathOfAlias('application.runtime.test_messages'); + $this->createDir($this->messagePath); + $this->configFileName=Yii::getPathOfAlias('application.runtime').DIRECTORY_SEPARATOR.'message_command_test_config.php'; + } + + public function tearDown() + { + $this->removeDir($this->sourcePath); + $this->removeDir($this->messagePath); + if(file_exists($this->configFileName)) + unlink($this->configFileName); + } + + /** + * Creates directory. + * @param $dirName directory full name + */ + protected function createDir($dirName) + { + if(!file_exists($dirName)) + mkdir($dirName,0777,true); + } + + /** + * Removes directory. + * @param $dirName directory full name + */ + protected function removeDir($dirName) + { + if(!empty($dirName) && file_exists($dirName)) + { + $this->removeFileSystemObject($dirName); + } + } + + /** + * Removes file system object: directory or file. + * @param string $fileSystemObjectFullName file system object full name. + */ + protected function removeFileSystemObject($fileSystemObjectFullName) + { + if(!is_dir($fileSystemObjectFullName)) + { + unlink($fileSystemObjectFullName); + } else { + $dirHandle = opendir($fileSystemObjectFullName); + while(($fileSystemObjectName=readdir($dirHandle))!==false) + { + if($fileSystemObjectName==='.' || $fileSystemObjectName==='..') + continue; + $this->removeFileSystemObject($fileSystemObjectFullName.DIRECTORY_SEPARATOR.$fileSystemObjectName); + } + closedir($dirHandle); + rmdir($fileSystemObjectFullName); + } + } + + /** + * @return MessageCommand message command instance + */ + protected function createMessageCommand() + { + //$command=new MessageCommand('message',null); + $command=$this->getMock('MessageCommand',array('usageError'),array('message',null)); + $command->expects($this->any())->method('usageError')->will($this->throwException(new CException('usageError'))); + return $command; + } + + /** + * Emulates running of the message command. + * @param array $args command shell arguments + * @return string command output + */ + protected function runMessageCommand(array $args) + { + $command=$this->createMessageCommand(); + ob_start(); + ob_implicit_flush(false); + $command->run($args); + return ob_get_clean(); + } + + /** + * Creates message command config file at {@link configFileName} + * @param array $config message command config. + */ + protected function composeConfigFile(array $config) + { + if(file_exists($this->configFileName)) + unlink($this->configFileName); + $fileContent='configFileName,$fileContent); + } + + /** + * Creates source file with given content + * @param string $content file content + * @param string|null $name file self name + */ + protected function createSourceFile($content,$name=null) + { + if(empty($name)) + $name=md5(uniqid()).'.php'; + file_put_contents($this->sourcePath.DIRECTORY_SEPARATOR.$name,$content); + } + + /** + * Creates message file with given messages. + * @param string $name file name + * @param array $messages messages. + */ + protected function createMessageFile($name,array $messages=array()) + { + $fileName=$this->messagePath.DIRECTORY_SEPARATOR.$name; + if(file_exists($fileName)) + unlink($fileName); + else + { + $dirName=dirname($fileName); + if(!file_exists($dirName)) + mkdir($dirName,0777,true); + } + $fileContent='setExpectedException('CException','usageError'); + $this->runMessageCommand(array()); + } + + public function testConfigFileNotExist() + { + $this->setExpectedException('CException','usageError'); + $this->runMessageCommand(array('not_existing_file.php')); + } + + public function testCreateTranslation() + { + $language = 'en'; + + $category='test_category'; + $message='test message'; + $sourceFileContent="Yii::t('{$category}','{$message}')"; + $this->createSourceFile($sourceFileContent); + + $this->composeConfigFile(array( + 'languages'=>array($language), + 'sourcePath'=>$this->sourcePath, + 'messagePath'=>$this->messagePath, + )); + $this->runMessageCommand(array($this->configFileName)); + + $this->assertTrue(file_exists($this->messagePath.DIRECTORY_SEPARATOR.$language),'No language dir created!'); + $messageFileName=$this->messagePath.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.$category.'.php'; + $this->assertTrue(file_exists($messageFileName),'No message file created!'); + $messages=require($messageFileName); + $this->assertTrue(is_array($messages),'Unable to compose messages!'); + $this->assertTrue(array_key_exists($message,$messages),'Source message is missing!'); + } + + /** + * @depends testCreateTranslation + */ + public function testNothingNew() + { + $language = 'en'; + + $category='test_category'; + $message='test message'; + $sourceFileContent = "Yii::t('{$category}','{$message}')"; + $this->createSourceFile($sourceFileContent); + + $this->composeConfigFile(array( + 'languages'=>array($language), + 'sourcePath'=>$this->sourcePath, + 'messagePath'=>$this->messagePath, + )); + $this->runMessageCommand(array($this->configFileName)); + + $messageFileName=$this->messagePath.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.$category.'.php'; + + // check file not overwritten: + $messageFileContent=file_get_contents($messageFileName); + $messageFileContent.='// some not generated by command content'; + file_put_contents($messageFileName,$messageFileContent); + + $this->runMessageCommand(array($this->configFileName)); + + $this->assertEquals($messageFileContent,file_get_contents($messageFileName)); + } + + /** + * @depends testCreateTranslation + */ + public function testMerge() + { + $language = 'en'; + $category='test_category'; + $messageFileName=$language.DIRECTORY_SEPARATOR.$category.'.php'; + + $existingMessage='test existing message'; + $existingMessageContent='test existing message content'; + $this->createMessageFile($messageFileName,array( + $existingMessage=>$existingMessageContent + )); + + $newMessage='test new message'; + $sourceFileContent = "Yii::t('{$category}','{$existingMessage}')"; + $sourceFileContent .= "Yii::t('{$category}','{$newMessage}')"; + $this->createSourceFile($sourceFileContent); + + $this->composeConfigFile(array( + 'languages'=>array($language), + 'sourcePath'=>$this->sourcePath, + 'messagePath'=>$this->messagePath, + 'overwrite'=>true, + )); + $this->runMessageCommand(array($this->configFileName)); + + $messages=require($this->messagePath.DIRECTORY_SEPARATOR.$messageFileName); + $this->assertTrue(array_key_exists($newMessage,$messages),'Unable to add new message!'); + $this->assertTrue(array_key_exists($existingMessage,$messages),'Unable to keep existing message!'); + $this->assertEquals('',$messages[$newMessage],'Wrong new message content!'); + $this->assertEquals($existingMessageContent,$messages[$existingMessage],'Unable to keep existing message content!'); + } + + /** + * @depends testMerge + */ + public function testNoLongerNeedTranslation() + { + $language = 'en'; + $category='test_category'; + $messageFileName=$language.DIRECTORY_SEPARATOR.$category.'.php'; + + $oldMessage='test old message'; + $oldMessageContent='test old message content'; + $this->createMessageFile($messageFileName,array( + $oldMessage=>$oldMessageContent + )); + + $sourceFileContent = "Yii::t('{$category}','some new message')"; + $this->createSourceFile($sourceFileContent); + + $this->composeConfigFile(array( + 'languages'=>array($language), + 'sourcePath'=>$this->sourcePath, + 'messagePath'=>$this->messagePath, + 'overwrite'=>true, + 'removeOld'=>false, + )); + $this->runMessageCommand(array($this->configFileName)); + + $messages=require($this->messagePath.DIRECTORY_SEPARATOR.$messageFileName); + + $this->assertTrue(array_key_exists($oldMessage,$messages),'No longer needed message removed!'); + $this->assertEquals('@@'.$oldMessageContent.'@@',$messages[$oldMessage],'No longer needed message content does not marked properly!'); + } + + /** + * @depends testMerge + * @see https://github.com/yiisoft/yii/issues/2244 + */ + public function testMergeWithContentZero() + { + $language = 'en'; + $category='test_category'; + $messageFileName=$language.DIRECTORY_SEPARATOR.$category.'.php'; + + $zeroMessage='test zero message'; + $zeroMessageContent='0'; + $falseMessage='test false message'; + $falseMessageContent='false'; + $this->createMessageFile($messageFileName,array( + $zeroMessage=>$zeroMessageContent, + $falseMessage=>$falseMessageContent, + )); + + $newMessage='test new message'; + $sourceFileContent = "Yii::t('{$category}','{$zeroMessage}')"; + $sourceFileContent .= "Yii::t('{$category}','{$falseMessage}')"; + $sourceFileContent .= "Yii::t('{$category}','{$newMessage}')"; + $this->createSourceFile($sourceFileContent); + + $this->composeConfigFile(array( + 'languages'=>array($language), + 'sourcePath'=>$this->sourcePath, + 'messagePath'=>$this->messagePath, + 'overwrite'=>true, + )); + $this->runMessageCommand(array($this->configFileName)); + + $messages=require($this->messagePath.DIRECTORY_SEPARATOR.$messageFileName); + $this->assertTrue($zeroMessageContent===$messages[$zeroMessage],'Message content "0" is lost!'); + $this->assertTrue($falseMessageContent===$messages[$falseMessage],'Message content "false" is lost!'); + } + + /** + * @depends testCreateTranslation + * @see https://github.com/yiisoft/yii/issues/1228 + */ + public function testMultiplyTranslators() + { + $language = 'en'; + $category='test_category'; + + $translators=array( + 'Yii::t', + 'Custom::translate', + ); + + $sourceMessages=array( + 'first message', + 'second message', + ); + $sourceFileContent=''; + foreach($sourceMessages as $key => $message) + $sourceFileContent.=$translators[$key]."('{$category}','{$message}');\n"; + $this->createSourceFile($sourceFileContent); + + $this->composeConfigFile(array( + 'languages'=>array($language), + 'sourcePath'=>$this->sourcePath, + 'messagePath'=>$this->messagePath, + 'translator'=>$translators, + )); + $this->runMessageCommand(array($this->configFileName)); + + $messageFileName=$this->messagePath.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.$category.'.php'; + $messages=require($messageFileName); + + foreach($sourceMessages as $sourceMessage) + $this->assertTrue(array_key_exists($sourceMessage,$messages)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CAttributeCollectionTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CAttributeCollectionTest.php new file mode 100644 index 0000000..bc60658 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CAttributeCollectionTest.php @@ -0,0 +1,126 @@ +Property = 'value'; + $this->assertEquals('value', $collection->Property); + $this->assertTrue($collection->canGetProperty('Property')); + } + + public function testCanNotGetUndefinedProperty() + { + $collection = new CAttributeCollection(array(), true); + $this->assertFalse($collection->canGetProperty('Property')); + $this->setExpectedException('CException'); + $value=$collection->Property; + } + + public function testCanSetProperty() + { + $collection = new CAttributeCollection(); + $collection->Property = 'value'; + $this->assertEquals('value', $collection->itemAt('Property')); + $this->assertTrue($collection->canSetProperty('Property')); + } + + public function testCanNotSetPropertyIfReadOnly() + { + $collection = new CAttributeCollection(array(), true); + $this->setExpectedException('CException'); + $collection->Property = 'value'; + } + + public function testGetCaseSensitive() + { + $collection = new CAttributeCollection(); + $collection->caseSensitive=false; + $this->assertFalse($collection->caseSensitive); + $collection->caseSensitive=true; + $this->assertTrue($collection->caseSensitive); + } + + public function testSetCaseSensitive() + { + $collection = new CAttributeCollection(); + $collection->Property = 'value'; + $collection->caseSensitive=false; + $this->assertEquals('value', $collection->itemAt('property')); + } + + public function testItemAt() + { + $collection = new CAttributeCollection(); + $collection->Property = 'value'; + $this->assertEquals('value', $collection->itemAt('Property')); + } + + public function testAdd() + { + $collection = new CAttributeCollection(); + $collection->add('Property', 'value'); + $this->assertEquals('value', $collection->itemAt('Property')); + } + + public function testRemove() + { + $collection = new CAttributeCollection(); + $collection->add('Property', 'value'); + $collection->remove('Property'); + $this->assertEquals(0, count($collection)); + } + + public function testUnset(){ + $collection = new CAttributeCollection(); + $collection->add('Property', 'value'); + unset($collection->Property); + $this->assertEquals(0, count($collection)); + } + + public function testIsset(){ + $collection = new CAttributeCollection(); + $this->assertFalse(isset($collection->Property)); + $collection->Property = 'value'; + $this->assertTrue(isset($collection->Property)); + } + + public function testContains() + { + $collection = new CAttributeCollection(); + $this->assertFalse($collection->contains('Property')); + $collection->Property = 'value'; + $this->assertTrue($collection->contains('Property')); + } + + public function testHasProperty() + { + $collection = new CAttributeCollection(); + $this->assertFalse($collection->hasProperty('Property')); + $collection->Property = 'value'; + $this->assertTrue($collection->hasProperty('Property')); + } + + public function testMergeWithCaseSensitive() + { + $collection = new CAttributeCollection(); + $item = array('Test'=>'Uppercase'); + $collection->mergeWith($item); + $this->assertEquals('Uppercase', $collection->itemAt('test')); + } + + public function testMergeWithCaseInSensitive() + { + $collection = new CAttributeCollection(); + $collection->caseSensitive = true; + $collection->add('k1','item'); + + $item = array('K1'=>'ITEM'); + $collection->mergeWith($item); + $this->assertEquals('item', $collection->itemAt('k1')); + $this->assertEquals('ITEM', $collection->itemAt('K1')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CConfigurationTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CConfigurationTest.php new file mode 100644 index 0000000..0612817 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CConfigurationTest.php @@ -0,0 +1,91 @@ +_param2; + } + + public function setParam2($value) + { + $this->_param2=$value; + } + + public function getObject() + { + if($this->_object===null) + $this->_object=new MyClass; + return $this->_object; + } +} + +class CConfigurationTest extends CTestCase +{ + public $configFile; + + public function setUp() + { + $this->configFile=dirname(__FILE__).'/data/config.php'; + } + + public function tearDown() + { + } + + public function testLoadFromFile() + { + $config=new CConfiguration; + $this->assertTrue($config->toArray()===array()); + $config->loadFromFile($this->configFile); + $data=include($this->configFile); + $this->assertTrue($config->toArray()===$data); + } + + public function testSaveAsString() + { + $config=new CConfiguration($this->configFile); + $str=$config->saveAsString(); + eval("\$data=$str;"); + $this->assertTrue($config->toArray()===$data); + } + + public function testApplyTo() + { + $config=new CConfiguration($this->configFile); + $object=new MyClass; + $config->applyTo($object); + $this->assertTrue($object->param1==='value1'); + $this->assertTrue($object->param2===false); + $this->assertTrue($object->param3===123); + $this->assertTrue($object->backquote==="\\back'quote'"); + /* + $this->assertTrue($object->object->param1===null); + $this->assertTrue($object->object->param2==='123'); + $this->assertTrue($object->object->param3===array('param1'=>'kkk','ddd','')); + */ + } + + public function testException() + { + $config=new CConfiguration(array('invalid'=>'value')); + $object=new MyClass; + $this->setExpectedException('CException'); + $config->applyTo($object); + } + + public function testCreateComponent() + { + $obj=Yii::createComponent(array('class'=>'MyClass','param2'=>3)); + $this->assertEquals(get_class($obj),'MyClass'); + $this->assertEquals($obj->param2,3); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CListTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CListTest.php new file mode 100644 index 0000000..38534f8 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CListTest.php @@ -0,0 +1,215 @@ +list=new CList; + $this->item1=new ListItem; + $this->item2=new ListItem; + $this->item3=new ListItem; + $this->list->add($this->item1); + $this->list->add($this->item2); + } + + public function tearDown() + { + $this->list=null; + $this->item1=null; + $this->item2=null; + $this->item3=null; + } + + public function testConstruct() + { + $a=array(1,2,3); + $list=new CList($a); + $this->assertEquals(3,$list->getCount()); + $list2=new CList($this->list); + $this->assertEquals(2,$list2->getCount()); + } + + public function testGetReadOnly() + { + $list = new CList(null, true); + $this->assertTrue($list->getReadOnly(), 'List is not read-only'); + $list = new CList(null, false); + $this->assertFalse($list->getReadOnly(), 'List is read-only'); + } + + public function testGetCount() + { + $this->assertEquals(2,$this->list->getCount()); + $this->assertEquals(2,$this->list->Count); + } + + public function testAdd() + { + $this->list->add(null); + $this->list->add($this->item3); + $this->assertEquals(4,$this->list->getCount()); + $this->assertEquals(3,$this->list->indexOf($this->item3)); + } + + public function testInsertAt() + { + $this->list->insertAt(0,$this->item3); + $this->assertEquals(3,$this->list->getCount()); + $this->assertEquals(2,$this->list->indexOf($this->item2)); + $this->assertEquals(0,$this->list->indexOf($this->item3)); + $this->assertEquals(1,$this->list->indexOf($this->item1)); + $this->setExpectedException('CException'); + $this->list->insertAt(4,$this->item3); + } + + public function testCanNotInsertWhenReadOnly() + { + $list = new CList(array(), true); + $this->setExpectedException('CException'); + $list->insertAt(1, 2); + } + + public function testRemove() + { + $this->list->remove($this->item1); + $this->assertEquals(1,$this->list->getCount()); + $this->assertEquals(-1,$this->list->indexOf($this->item1)); + $this->assertEquals(0,$this->list->indexOf($this->item2)); + + $this->assertFalse($this->list->remove($this->item1)); + + } + + public function testRemoveAt() + { + $this->list->add($this->item3); + $this->list->removeAt(1); + $this->assertEquals(-1,$this->list->indexOf($this->item2)); + $this->assertEquals(1,$this->list->indexOf($this->item3)); + $this->assertEquals(0,$this->list->indexOf($this->item1)); + $this->setExpectedException('CException'); + $this->list->removeAt(2); + } + + public function testCanNotRemoveWhenReadOnly() + { + $list = new CList(array(1, 2, 3), true); + $this->setExpectedException('CException'); + $list->removeAt(2); + } + + public function testClear() + { + $this->list->clear(); + $this->assertEquals(0,$this->list->getCount()); + $this->assertEquals(-1,$this->list->indexOf($this->item1)); + $this->assertEquals(-1,$this->list->indexOf($this->item2)); + } + + public function testContains() + { + $this->assertTrue($this->list->contains($this->item1)); + $this->assertTrue($this->list->contains($this->item2)); + $this->assertFalse($this->list->contains($this->item3)); + } + + public function testIndexOf() + { + $this->assertEquals(0,$this->list->indexOf($this->item1)); + $this->assertEquals(1,$this->list->indexOf($this->item2)); + $this->assertEquals(-1,$this->list->indexOf($this->item3)); + } + + public function testCopyFrom() + { + $array=array($this->item3,$this->item1); + $this->list->copyFrom($array); + $this->assertTrue(count($array)==2 && $this->list[0]===$this->item3 && $this->list[1]===$this->item1); + $this->setExpectedException('CException'); + $this->list->copyFrom($this); + } + + public function testMergeWith() + { + $array=array($this->item3,$this->item1); + $this->list->mergeWith($array); + $this->assertTrue($this->list->getCount()==4 && $this->list[0]===$this->item1 && $this->list[3]===$this->item1); + $this->setExpectedException('CException'); + $this->list->mergeWith($this); + } + + public function testToArray() + { + $array=$this->list->toArray(); + $this->assertTrue(count($array)==2 && $array[0]===$this->item1 && $array[1]===$this->item2); + } + + public function testArrayRead() + { + $this->assertTrue($this->list[0]===$this->item1); + $this->assertTrue($this->list[1]===$this->item2); + $this->setExpectedException('CException'); + $a=$this->list[2]; + } + + public function testGetIterator() + { + $n=0; + $found=0; + foreach($this->list as $index=>$item) + { + foreach($this->list as $a=>$b); // test of iterator + $n++; + if($index===0 && $item===$this->item1) + $found++; + if($index===1 && $item===$this->item2) + $found++; + } + $this->assertTrue($n==2 && $found==2); + } + + public function testArrayMisc() + { + $this->assertEquals($this->list->Count,count($this->list)); + $this->assertTrue(isset($this->list[1])); + $this->assertFalse(isset($this->list[2])); + } + + public function testOffsetSetAdd() + { + $list = new CList(array(1, 2, 3)); + $list->offsetSet(null, 4); + $this->assertEquals(array(1, 2, 3, 4), $list->toArray()); + } + + public function testOffsetSetReplace() + { + $list = new CList(array(1, 2, 3)); + $list->offsetSet(1, 4); + $this->assertEquals(array(1, 4, 3), $list->toArray()); + } + + public function testOffsetUnset() + { + $list = new CList(array(1, 2, 3)); + $list->offsetUnset(1); + $this->assertEquals(array(1, 3), $list->toArray()); + } + + public function testIteratorCurrent() + { + $list = new CList(array('value1', 'value2')); + $val = $list->getIterator()->current(); + $this->assertEquals('value1', $val); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CMapTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CMapTest.php new file mode 100644 index 0000000..5695c3e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CMapTest.php @@ -0,0 +1,211 @@ +map=new CMap; + $this->item1=new MapItem; + $this->item2=new MapItem; + $this->item3=new MapItem; + $this->map->add('key1',$this->item1); + $this->map->add('key2',$this->item2); + } + + public function tearDown() + { + $this->map=null; + $this->item1=null; + $this->item2=null; + $this->item3=null; + } + + public function testConstruct() + { + $a=array(1,2,'key3'=>3); + $map=new CMap($a); + $this->assertEquals(3,$map->getCount()); + $map2=new CMap($this->map); + $this->assertEquals(2,$map2->getCount()); + } + + public function testGetReadOnly() + { + $map = new CMap(null, true); + self::assertEquals(true, $map->getReadOnly(), 'List is not read-only'); + } + + public function testGetCount() + { + $this->assertEquals(2,$this->map->getCount()); + } + + public function testGetKeys() + { + $keys=$this->map->getKeys(); + $this->assertEquals(2,count($keys)); + $this->assertEquals('key1',$keys[0]); + $this->assertEquals('key2',$keys[1]); + } + + public function testAdd() + { + $this->map->add('key3',$this->item3); + $this->assertEquals(3,$this->map->getCount()); + $this->assertTrue($this->map->contains('key3')); + } + + public function testCanNotAddWhenReadOnly() + { + $map = new CMap(array(), true); + $this->setExpectedException('CException'); + $map->add('key', 'value'); + } + + public function testRemove() + { + $this->map->remove('key1'); + $this->assertEquals(1,$this->map->getCount()); + $this->assertTrue(!$this->map->contains('key1')); + $this->assertTrue($this->map->remove('unknown key')===null); + } + + public function testCanNotRemoveWhenReadOnly() + { + $map = new CMap(array('key' => 'value'), true); + $this->setExpectedException('CException'); + $map->remove('key'); + } + + public function testClear() + { + $this->map->clear(); + $this->assertEquals(0,$this->map->getCount()); + $this->assertTrue(!$this->map->contains('key1') && !$this->map->contains('key2')); + } + + public function testContains() + { + $this->assertTrue($this->map->contains('key1')); + $this->assertTrue($this->map->contains('key2')); + $this->assertFalse($this->map->contains('key3')); + } + + public function testCopyFrom() + { + $array=array('key3'=>$this->item3,'key4'=>$this->item1); + $this->map->copyFrom($array); + + $this->assertEquals(2, $this->map->getCount()); + $this->assertEquals($this->item3, $this->map['key3']); + $this->assertEquals($this->item1, $this->map['key4']); + + $this->setExpectedException('CException'); + $this->map->copyFrom($this); + } + + public function testMergeWith() + { + $a=array('a'=>'v1','v2',array('2'),'c'=>array('3','c'=>'a')); + $b=array('v22','a'=>'v11',array('2'),'c'=>array('c'=>'3','a')); + $c=array('a'=>'v11','v2',array('2'),'c'=>array('3','c'=>'3','a'),'v22',array('2')); + $map=new CMap($a); + $map2=new CMap($b); + $map->mergeWith($map2); + $this->assertTrue($map->toArray()===$c); + + $array=array('key2'=>$this->item1,'key3'=>$this->item3); + $this->map->mergeWith($array,false); + $this->assertEquals(3,$this->map->getCount()); + $this->assertEquals($this->item1,$this->map['key2']); + $this->assertEquals($this->item3,$this->map['key3']); + $this->setExpectedException('CException'); + $this->map->mergeWith($this,false); + } + + public function testRecursiveMergeWithTraversable(){ + $map = new CMap(); + $obj = new ArrayObject(array( + 'k1' => $this->item1, + 'k2' => $this->item2, + 'k3' => new ArrayObject(array( + 'k4' => $this->item3, + )) + )); + $map->mergeWith($obj,true); + + $this->assertEquals(3, $map->getCount()); + $this->assertEquals($this->item1, $map['k1']); + $this->assertEquals($this->item2, $map['k2']); + $this->assertEquals($this->item3, $map['k3']['k4']); + } + + public function testArrayRead() + { + $this->assertEquals($this->item1,$this->map['key1']); + $this->assertEquals($this->item2,$this->map['key2']); + $this->assertNull($this->map['key3']); + } + + public function testArrayWrite() + { + $this->map['key3']=$this->item3; + $this->assertEquals(3,$this->map->getCount()); + $this->assertEquals($this->item3,$this->map['key3']); + + $this->map['key1']=$this->item3; + $this->assertEquals(3,$this->map->getCount()); + $this->assertEquals($this->item3,$this->map['key1']); + + unset($this->map['key2']); + $this->assertEquals(2,$this->map->getCount()); + $this->assertTrue(!$this->map->contains('key2')); + + unset($this->map['unknown key']); + } + + public function testArrayForeach() + { + $n=0; + $found=0; + foreach($this->map as $index=>$item) + { + $n++; + if($index==='key1' && $item===$this->item1) + $found++; + if($index==='key2' && $item===$this->item2) + $found++; + } + $this->assertTrue($n==2 && $found==2); + } + + public function testArrayMisc() + { + $this->assertEquals($this->map->Count,count($this->map)); + $this->assertTrue(isset($this->map['key1'])); + $this->assertFalse(isset($this->map['unknown key'])); + } + + public function testToArray() + { + $map = new CMap(array('key' => 'value')); + $this->assertEquals(array('key' => 'value'), $map->toArray()); + } + + public function testIteratorCurrent() + { + $map = new CMap(array('key1' => 'value1', 'key2' => 'value2')); + $val = $map->getIterator()->current(); + $this->assertEquals('value1', $val); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CQueueTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CQueueTest.php new file mode 100644 index 0000000..9917787 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CQueueTest.php @@ -0,0 +1,119 @@ +assertEquals(array(), $queue->toArray()); + $queue = new CQueue(array(1, 2, 3)); + $this->assertEquals(array(1, 2, 3), $queue->toArray()); + } + + public function testToArray() + { + $queue = new CQueue(array(1, 2, 3)); + $this->assertEquals(array(1, 2, 3), $queue->toArray()); + } + + public function testCopyFrom() + { + $queue = new CQueue(array(1, 2, 3)); + $data = array(4, 5, 6); + $queue->copyFrom($data); + $this->assertEquals(array(4, 5, 6), $queue->toArray()); + } + + public function testCanNotCopyFromNonTraversableTypes() + { + $queue = new CQueue(); + $data = new stdClass(); + $this->setExpectedException('CException'); + $queue->copyFrom($data); + } + + public function testClear() + { + $queue = new CQueue(array(1, 2, 3)); + $queue->clear(); + $this->assertEquals(array(), $queue->toArray()); + } + + public function testContains() + { + $queue = new CQueue(array(1, 2, 3)); + $this->assertTrue($queue->contains(2)); + $this->assertFalse($queue->contains(4)); + } + + public function testPeek() + { + $queue = new CQueue(array(1)); + $this->assertEquals(1, $queue->peek()); + } + + public function testCanNotPeekAnEmptyQueue() + { + $queue = new CQueue(); + $this->setExpectedException('CException'); + $item = $queue->peek(); + } + + public function testDequeue() + { + $queue = new CQueue(array(1, 2, 3)); + $first = $queue->dequeue(); + $this->assertEquals(1, $first); + $this->assertEquals(array(2, 3), $queue->toArray()); + } + + public function testCanNotDequeueAnEmptyQueue() + { + $queue = new CQueue(); + $this->setExpectedException('CException'); + $item = $queue->dequeue(); + } + + public function testEnqueue() + { + $queue = new CQueue(); + $queue->enqueue(1); + $this->assertEquals(array(1), $queue->toArray()); + } + + public function testGetIterator() + { + $queue = new CQueue(array(1, 2)); + $this->assertInstanceOf('CQueueIterator', $queue->getIterator()); + $n = 0; + $found = 0; + foreach($queue as $index => $item) + { + foreach($queue as $a => $b); // test of iterator + $n++; + if($index === 0 && $item === 1) + $found++; + if($index === 1 && $item === 2) + $found++; + } + $this->assertTrue($n == 2 && $found == 2); + } + + public function testGetCount() + { + $queue = new CQueue(); + $this->assertEquals(0, $queue->getCount()); + $queue = new CQueue(array(1, 2, 3)); + $this->assertEquals(3, $queue->getCount()); + } + + public function testCountable() + { + $queue = new CQueue(); + $this->assertEquals(0, count($queue)); + $queue = new CQueue(array(1, 2, 3)); + $this->assertEquals(3, count($queue)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CStackTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CStackTest.php new file mode 100644 index 0000000..01ff933 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CStackTest.php @@ -0,0 +1,119 @@ +assertEquals(array(), $stack->toArray()); + $stack = new CStack(array(1, 2, 3)); + $this->assertEquals(array(1, 2, 3), $stack->toArray()); + } + + public function testToArray() + { + $stack = new CStack(array(1, 2, 3)); + $this->assertEquals(array(1, 2, 3), $stack->toArray()); + } + + public function testCopyFrom() + { + $stack = new CStack(array(1, 2, 3)); + $data = array(4, 5, 6); + $stack->copyFrom($data); + $this->assertEquals(array(4, 5, 6), $stack->toArray()); + } + + public function testCanNotCopyFromNonTraversableTypes() + { + $stack = new CStack(); + $data = new stdClass(); + $this->setExpectedException('CException'); + $stack->copyFrom($data); + } + + public function testClear() + { + $stack = new CStack(array(1, 2, 3)); + $stack->clear(); + $this->assertEquals(array(), $stack->toArray()); + } + + public function testContains() + { + $stack = new CStack(array(1, 2, 3)); + $this->assertTrue($stack->contains(2)); + $this->assertFalse($stack->contains(4)); + } + + public function testPeek() + { + $stack = new CStack(array(1)); + $this->assertEquals(1, $stack->peek()); + } + + public function testCanNotPeekAnEmptyStack() + { + $stack = new CStack(); + $this->setExpectedException('CException'); + $item = $stack->peek(); + } + + public function testPop() + { + $stack = new CStack(array(1, 2, 3)); + $last = $stack->pop(); + $this->assertEquals(3, $last); + $this->assertEquals(array(1, 2), $stack->toArray()); + } + + public function testCanNotPopAnEmptyStack() + { + $stack = new CStack(); + $this->setExpectedException('CException'); + $item = $stack->pop(); + } + + public function testPush() + { + $stack = new CStack(); + $stack->push(1); + $this->assertEquals(array(1), $stack->toArray()); + } + + public function testGetIterator() + { + $stack = new CStack(array(1, 2)); + $this->assertInstanceOf('CStackIterator', $stack->getIterator()); + $n = 0; + $found = 0; + foreach($stack as $index => $item) + { + foreach($stack as $a => $b); // test of iterator + $n++; + if($index === 0 && $item === 1) + $found++; + if($index === 1 && $item === 2) + $found++; + } + $this->assertTrue($n == 2 && $found == 2); + } + + public function testGetCount() + { + $stack = new CStack(); + $this->assertEquals(0, $stack->getCount()); + $stack = new CStack(array(1, 2, 3)); + $this->assertEquals(3, $stack->getCount()); + } + + public function testCount() + { + $stack = new CStack(); + $this->assertEquals(0, count($stack)); + $stack = new CStack(array(1, 2, 3)); + $this->assertEquals(3, count($stack)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CTypedListTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CTypedListTest.php new file mode 100644 index 0000000..f035413 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CTypedListTest.php @@ -0,0 +1,22 @@ +setExpectedException('CException'); + $list[]=new stdClass; + } + + public function testInterfaceType() + { + $list=new CTypedList('Traversable'); + $list[]=new CList; + $this->setExpectedException('CException'); + $list[]=new CComponent; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CTypedMapTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CTypedMapTest.php new file mode 100644 index 0000000..f925737 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/CTypedMapTest.php @@ -0,0 +1,23 @@ +add(0, new CTypedMapTestFoo()); + } + + public function testAddWrongType() + { + $this->setExpectedException('CException'); + + $typedMap = new CTypedMap('CTypedMapTestFoo'); + $typedMap->add(0, new CTypedMapTestBar()); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/data/config.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/data/config.php new file mode 100644 index 0000000..921bccd --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/collections/data/config.php @@ -0,0 +1,17 @@ +'value1', + 'param2'=>false, + 'param3'=>123, + "backquote"=>"\\back'quote'", +/* 'object'=>array( + 'param1'=>null, + 'param2'=>'123', + 'param3'=>array( + 'param1'=>'kkk', + 'ddd', + '', + ), + ),*/ +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommand2Test.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommand2Test.php new file mode 100644 index 0000000..3e114d9 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommand2Test.php @@ -0,0 +1,451 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + } + + public function tearDown() + { + $this->_connection->active=false; + } + + public function testSelect() + { + $command=$this->_connection->createCommand(); + + // default + $command->select(); + $this->assertEquals('*', $command->select); + + // string input + $command->select('id, username'); + $this->assertEquals('"id", "username"', $command->select); + + // string input with expression + $command->select('id, count(id) as num'); + $this->assertEquals('id, count(id) as num', $command->select); + + // array input + $command->select(array('id2', 'username2')); + $this->assertEquals('"id2", "username2"', $command->select); + + // table prefix and expression + $command->select(array('user.id', 'count(id) as num', 'profile.*')); + $this->assertEquals('\'user\'."id", count(id) as num, \'profile\'.*', $command->select); + + // alias + $command->select(array('id2 as id', 'profile.username2 AS username')); + $this->assertEquals('"id2" AS "id", \'profile\'."username2" AS "username"', $command->select); + + // getter and setter + $command->select=array('id2', 'username2'); + $this->assertEquals('"id2", "username2"', $command->select); + } + + public function testDistinct() + { + $command=$this->_connection->createCommand(); + + // default value + $this->assertFalse($command->distinct); + + // select distinct + $command->selectDistinct('id, username'); + $this->assertTrue($command->distinct); + $this->assertEquals('"id", "username"', $command->select); + + // getter and setter + $command->distinct=false; + $this->assertFalse($command->distinct); + $command->distinct=true; + $this->assertTrue($command->distinct); + } + + public function testFrom() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->from); + + // string input + $command->from('user'); + $this->assertEquals('\'user\'', $command->from); + $command->from('user, profile'); + $this->assertEquals('\'user\', \'profile\'', $command->from); + + // string input with expression + $command->from('user, (select * from profile) p'); + $this->assertEquals('user, (select * from profile) p', $command->from); + + // array input + $command->from(array('user', 'profile')); + $this->assertEquals('\'user\', \'profile\'', $command->from); + + // table alias, expression, schema + $command->from(array('user u', '(select * from profile) p', 'public.post')); + $this->assertEquals('\'user\' \'u\', (select * from profile) p, \'public\'.\'post\'', $command->from); + + // getter and setter + $command->from=array('user', 'profile'); + $this->assertEquals('\'user\', \'profile\'', $command->from); + } + + public function testWhere() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->where); + $this->assertEquals(array(), $command->params); + + // string input + $command->where('id=1 or id=:id2', array(':id2'=>2)); + $this->assertEquals('id=1 or id=:id2', $command->where); + $this->assertEquals(array(':id2'=>2), $command->params); + + // array input, and/or + $command->where(array('and', 'id=1', 'id=2')); + $this->assertEquals('(id=1) AND (id=2)', $command->where); + $command->where(array('and', 'id=1', array('or', 'id=3', 'id=4'), 'id=2')); + $this->assertEquals('(id=1) AND ((id=3) OR (id=4)) AND (id=2)', $command->where); + + // empty input + $command->where(array()); + $this->assertEquals('', $command->where); + + // in, empty + $command->where(array('in', 'id', array())); + $this->assertEquals('0=1', $command->where); + + // in + $command->where(array('in', 'id', array(1,'2',3))); + $this->assertEquals("\"id\" IN (1, '2', 3)", $command->where); + + // not in, empty + $command->where(array('not in', 'id', array())); + $this->assertEquals('', $command->where); + + // not in + $command->where(array('not in', 'id', array(1,'2',3))); + $this->assertEquals("\"id\" NOT IN (1, '2', 3)", $command->where); + + // like, string + $command->where(array('like', 'name', '%tester')); + $this->assertEquals('"name" LIKE \'%tester\'', $command->where); + + $command->where(array('like', 'name', array('%tester', '%tester2'))); + $this->assertEquals('"name" LIKE \'%tester\' AND "name" LIKE \'%tester2\'', $command->where); + + $command->where(array('not like', 'name', array('tester%', 'tester2%'))); + $this->assertEquals('"name" NOT LIKE \'tester%\' AND "name" NOT LIKE \'tester2%\'', $command->where); + + $command->where(array('or like', 'name', array('%tester', '%tester2'))); + $this->assertEquals('"name" LIKE \'%tester\' OR "name" LIKE \'%tester2\'', $command->where); + + $command->where(array('or not like', 'name', array('%tester', '%tester2'))); + $this->assertEquals('"name" NOT LIKE \'%tester\' OR "name" NOT LIKE \'%tester2\'', $command->where); + } + + public function testAndWhere() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->where); + $this->assertEquals(array(), $command->params); + + // string input + $command->andWhere('id=1 or id=:id2', array(':id2'=>2)); + $this->assertEquals('id=1 or id=:id2', $command->where); + $this->assertEquals(array(':id2'=>2), $command->params); + + // array input, and/or + $command->andWhere(array('and', 'id=1', 'id=2')); + $this->assertEquals('(id=1 or id=:id2) AND ((id=1) AND (id=2))', $command->where); + $command->andWhere(array('and', 'id=1', array('or', 'id=3', 'id=4'), 'id=2'), array()); + $this->assertEquals('((id=1 or id=:id2) AND ((id=1) AND (id=2))) AND ((id=1) AND ((id=3) OR (id=4)) AND (id=2))', $command->where); + + // empty input + $command->andWhere(array()); + $this->assertEquals('(((id=1 or id=:id2) AND ((id=1) AND (id=2))) AND ((id=1) AND ((id=3) OR (id=4)) AND (id=2)))', $command->where); + } + + public function testOrWhere() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->where); + $this->assertEquals(array(), $command->params); + + // string input + $command->orWhere('id=1 or id=:id2', array(':id2'=>2)); + $this->assertEquals('id=1 or id=:id2', $command->where); + $this->assertEquals(array(':id2'=>2), $command->params); + + // array input, and/or + $command->orWhere(array('and', 'id=1', 'id=2')); + $this->assertEquals('(id=1 or id=:id2) OR ((id=1) AND (id=2))', $command->where); + $command->orWhere(array('and', 'id=1', array('or', 'id=3', 'id=4'), 'id=2'), array()); + $this->assertEquals('((id=1 or id=:id2) OR ((id=1) AND (id=2))) OR ((id=1) AND ((id=3) OR (id=4)) AND (id=2))', $command->where); + + // empty input + $command->orWhere(array()); + $this->assertEquals('(((id=1 or id=:id2) OR ((id=1) AND (id=2))) OR ((id=1) AND ((id=3) OR (id=4)) AND (id=2)))', $command->where); + } + + public function testJoin() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->join); + + // inner join + $command->join('user', 'user.id=t.id and id=:id', array(':id'=>1)); + $this->assertEquals(array('JOIN \'user\' ON user.id=t.id and id=:id'), $command->join); + $this->assertEquals(array(':id'=>1), $command->params); + + // left join + $join=$command->join; + $command->leftJoin('user', 'user.id=t.id and id=:id'); + $join[]='LEFT JOIN \'user\' ON user.id=t.id and id=:id'; + $this->assertEquals($join, $command->join); + + // right join + $command->rightJoin('user', 'user.id=t.id and id=:id'); + $join[]='RIGHT JOIN \'user\' ON user.id=t.id and id=:id'; + $this->assertEquals($join, $command->join); + + // cross join + $command->crossJoin('user'); + $join[]='CROSS JOIN \'user\''; + $this->assertEquals($join, $command->join); + + // natural join + $command->naturalJoin('user'); + $join[]='NATURAL JOIN \'user\''; + $this->assertEquals($join, $command->join); + } + + public function testGroup() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->group); + + // string input + $command->group('id, username'); + $this->assertEquals('"id", "username"', $command->group); + + // string input with expression + $command->group('id, count(id)'); + $this->assertEquals('id, count(id)', $command->group); + + // array input + $command->group(array('id2', 'username2')); + $this->assertEquals('"id2", "username2"', $command->group); + + // table prefix and expression + $command->group(array('user.id', 'count(id)')); + $this->assertEquals('\'user\'."id", count(id)', $command->group); + + // getter and setter + $command->group=array('id2', 'username2'); + $this->assertEquals('"id2", "username2"', $command->group); + } + + public function testHaving() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->having); + $this->assertEquals(array(), $command->params); + + // string input + $command->having('id=1 or id=:id2', array(':id2'=>2)); + $this->assertEquals('id=1 or id=:id2', $command->having); + $this->assertEquals(array(':id2'=>2), $command->params); + + // array input, and/or + $command->having(array('and', 'id=1', 'id=2')); + $this->assertEquals('(id=1) AND (id=2)', $command->having); + $command->having(array('and', 'id=1', array('or', 'id=3', 'id=4'), 'id=2')); + $this->assertEquals('(id=1) AND ((id=3) OR (id=4)) AND (id=2)', $command->having); + } + + public function testOrder() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->order); + + // string input + $command->order('id, username desc'); + $this->assertEquals('"id", "username" DESC', $command->order); + + // string input with expression + $command->order('id, count(id) desc'); + $this->assertEquals('id, count(id) desc', $command->order); + + // array input + $command->order(array('id2 asc', 'username2 DESC')); + $this->assertEquals('"id2" ASC, "username2" DESC', $command->order); + + // table prefix and expression + $command->order(array('user.id asc', 'count(id)')); + $this->assertEquals('\'user\'."id" ASC, count(id)', $command->order); + + // getter and setter + $command->order=array('id2 asc', 'username2'); + $this->assertEquals('"id2" ASC, "username2"', $command->order); + } + + public function testLimit() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals(-1, $command->limit); + + $command->limit(10); + $this->assertEquals(10, $command->limit); + + $command->limit(20,30); + $this->assertEquals(20, $command->limit); + $this->assertEquals(30, $command->offset); + + // invalid string + $command->limit('abc'); + $this->assertEquals(0, $command->limit); + } + + public function testOffset() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals(-1, $command->offset); + + $command->offset(10); + $this->assertEquals(10, $command->offset); + + // invalid string + $command->offset('abc'); + $this->assertEquals(0, $command->offset); + } + + public function testUnion() + { + $command=$this->_connection->createCommand(); + + // default + $this->assertEquals('', $command->union); + + $command->union('select * from user'); + $this->assertEquals(array('select * from user'), $command->union); + + $command->union('select * from post'); + $this->assertEquals(array('select * from user', 'select * from post'), $command->union); + } + + /* + public function testInsert() + { + $command=$this->_connection->createCommand(); + + $command->insert('user', array('id'=>1, 'username'=>'tester')); + $this->assertEquals('INSERT INTO \'user\' ("id", "username") VALUES (:id, :username)', $command->text); + $this->assertEquals(array(':id'=>1, ':username'=>'tester'), $command->params); + } + + public function testUpdate() + { + $command=$this->_connection->createCommand(); + + $command->update('user', array('id'=>1, 'username'=>'tester'), 'status=:status', array(':status'=>2)); + $this->assertEquals('UPDATE \'user\' SET "id"=:id, "username"=:username WHERE status=:status', $command->text); + $this->assertEquals(array(':id'=>1, ':username'=>'tester', ':status'=>2), $command->params); + } + + public function testDelete() + { + $command=$this->_connection->createCommand(); + + $command->delete('user', 'status=:status', array(':status'=>2)); + $this->assertEquals('DELETE FROM \'user\' WHERE status=:status', $command->text); + $this->assertEquals(array(':status'=>2), $command->params); + } + */ + + public function testQuery() + { + // simple query + $command=$this->_connection->createCommand() + ->select('username, password') + ->from('users') + ->where('email=:email or email=:email2', array(':email'=>'email2', ':email2'=>'email4')) + ->order('username desc') + ->limit(2,1); + + $sql="SELECT \"username\", \"password\"\nFROM 'users'\nWHERE email=:email or email=:email2\nORDER BY \"username\" DESC LIMIT 2 OFFSET 1"; + $this->assertEquals($sql, $command->text); + + $rows=$command->queryAll(); + $this->assertEquals(1,count($rows)); + $this->assertEquals('user2',$rows[0]['username']); + $this->assertEquals('pass2',$rows[0]['password']); + } + + public function testArraySyntax() + { + $command=$this->_connection->createCommand(array( + 'select'=>'username, password', + 'from'=>'users', + 'where'=>'email=:email or email=:email2', + 'params'=>array(':email'=>'email2', ':email2'=>'email4'), + 'order'=>'username desc', + 'limit'=>2, + 'offset'=>1, + )); + + $sql="SELECT \"username\", \"password\"\nFROM 'users'\nWHERE email=:email or email=:email2\nORDER BY \"username\" DESC LIMIT 2 OFFSET 1"; + $this->assertEquals($sql, $command->text); + + $rows=$command->queryAll(); + $this->assertEquals(1,count($rows)); + $this->assertEquals('user2',$rows[0]['username']); + $this->assertEquals('pass2',$rows[0]['password']); + } + /** + * Belongs to #1045 + */ + public function testEmptyArray() + { + $command=$this->_connection->createCommand(); + $conditions=''; + $params=array(); + $query = $command->select('*') + ->from('tbl') + ->where($conditions, $params) + ->order('id ASC') + ->getText(); + $this->assertEquals("SELECT *\nFROM 'tbl'\nORDER BY \"id\" ASC", $query); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommandBuilderTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommandBuilderTest.php new file mode 100644 index 0000000..7d17809 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommandBuilderTest.php @@ -0,0 +1,206 @@ +markTestSkipped('PDO and MySQL extensions are required.'); + + $this->db=new CDbConnection('mysql:host=127.0.0.1;dbname=yii','test','test'); + $this->db->charset='UTF8'; + $this->db->enableParamLogging=true; + try + { + $this->db->active=true; + } + catch(Exception $e) + { + $schemaFile=realpath(dirname(__FILE__).'/data/mysql.sql'); + $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for MySQL test case."); + } + + $tables=array('comments','post_category','posts','categories','profiles','users','items','orders','types'); + foreach($tables as $table) + $this->db->createCommand("DROP TABLE IF EXISTS $table CASCADE")->execute(); + + $sqls=file_get_contents(dirname(__FILE__).'/data/mysql.sql'); + foreach(explode(';',$sqls) as $sql) + { + if(trim($sql)!=='') + $this->db->createCommand($sql)->execute(); + } + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testIssue1407_1() + { + // :parameter1 and :parameter2 should be removed inside CDbCommandBuilder::createCountCommand() + $tableSchema=$this->db->getSchema()->getTable('users'); + $builder=$this->db->getSchema()->getCommandBuilder(); + + $criteria1=new CDbCriteria(); + $criteria1->select=array('t.*',':parameter1 AS test'); + $criteria1->params[':parameter1']='testingValue'; + $criteria1->order='IF (t.username=:parameter2,t.username,t.email) DESC'; + $criteria1->params[':parameter2']='user2'; + $criteria1->addCondition('t.email LIKE :parameter4'); + $criteria1->params[':parameter4']='email%'; + $criteria1->addInCondition('t.id',array(1,2,3)); + + $criteria2=clone $criteria1; + + $this->assertEquals(3,$builder->createCountCommand($tableSchema,$criteria1)->queryScalar()); + + $result=$builder->createFindCommand($tableSchema,$criteria2)->queryAll(); + $this->assertCount(3,$result); + $this->assertEquals(array( + array( + 'id'=>'2', + 'username'=>'user2', + 'email'=>'email2', + 'test'=>'testingValue', + 'password'=>'pass2', + ), + array( + 'id'=>'3', + 'username'=>'user3', + 'email'=>'email3', + 'test'=>'testingValue', + 'password'=>'pass3', + ), + array( + 'id'=>'1', + 'username'=>'user1', + 'email'=>'email1', + 'test'=>'testingValue', + 'password'=>'pass1', + ), + ),$result); + } + + public function testIssue1407_2() + { + // :parameter1 is not used in SQL, thus exception should be thrown + $tableSchema=$this->db->getSchema()->getTable('users'); + $builder=$this->db->getSchema()->getCommandBuilder(); + + $criteria=new CDbCriteria(); + $criteria->select=array('t.*'); + $criteria->params[':parameter1']='testingValue'; + $criteria->order='IF (t.username=:parameter2,t.username,t.email) DESC'; + $criteria->params[':parameter2']='user2'; + $criteria->addCondition('t.email LIKE :parameter4'); + $criteria->params[':parameter4']='email%'; + $criteria->addInCondition('t.id',array(1,2,3)); + + $this->setExpectedException('CDbException'); + $builder->createCountCommand($tableSchema,$criteria)->queryScalar(); + } + + public function testIssue1407_3() + { + // :parameter2 is not used in SQL, thus exception should be thrown + $tableSchema=$this->db->getSchema()->getTable('users'); + $builder=$this->db->getSchema()->getCommandBuilder(); + + $criteria=new CDbCriteria(); + $criteria->select=array('t.*',':parameter1 AS test'); + $criteria->params[':parameter1']='testingValue'; + $criteria->order='IF (t.username="user2",t.username,t.email) DESC'; + $criteria->params[':parameter2']='user2'; + $criteria->addCondition('t.email LIKE :parameter4'); + $criteria->params[':parameter4']='email%'; + $criteria->addInCondition('t.id',array(1,2,3)); + + $this->setExpectedException('CDbException'); + $builder->createCountCommand($tableSchema,$criteria)->queryScalar(); + } + + public function testIssue1407_4() + { + // both :parameter1 and :parameter2 are not used in SQL, thus exception should be thrown + $tableSchema=$this->db->getSchema()->getTable('users'); + $builder=$this->db->getSchema()->getCommandBuilder(); + + $criteria=new CDbCriteria(); + $criteria->select=array('t.*'); + $criteria->params[':parameter1']='testingValue'; + $criteria->order='IF (t.username="user2",t.username,t.email) DESC'; + $criteria->params[':parameter2']='user2'; + $criteria->addCondition('t.email LIKE :parameter4'); + $criteria->params[':parameter4']='email%'; + $criteria->addInCondition('t.id',array(1,2,3)); + + $this->setExpectedException('CDbException'); + $builder->createCountCommand($tableSchema,$criteria)->queryScalar(); + } + + public function testIssue1407_5() + { + // :parameter3 is not used + $tableSchema=$this->db->getSchema()->getTable('users'); + $builder=$this->db->getSchema()->getCommandBuilder(); + + $criteria=new CDbCriteria(); + $criteria->select=array('t.*',':parameter1 AS test'); + $criteria->params[':parameter1']='testingValue'; + $criteria->order='IF (t.username=:parameter2,t.username,t.email) DESC'; + $criteria->params[':parameter2']='user2'; + $criteria->params[':parameter3']='parameter3Value'; + $criteria->addCondition('t.email LIKE :parameter4'); + $criteria->params[':parameter4']='email%'; + $criteria->addInCondition('t.id',array(1,2,3)); + + $this->setExpectedException('CDbException'); + $builder->createCountCommand($tableSchema,$criteria)->queryScalar(); + } + + public function testMultipleInsert() + { + $builder=$this->db->getSchema()->getCommandBuilder(); + $tableName='types'; + $data=array( + array( + 'int_col'=>1, + 'char_col'=>'char_col_1', + 'char_col2'=>'char_col_2_1', + 'float_col'=>1.1, + 'bool_col'=>true, + ), + array( + 'int_col'=>2, + 'char_col'=>'char_col_2', + 'float_col'=>2.2, + 'bool_col'=>false, + ), + ); + $command=$builder->createMultipleInsertCommand($tableName,$data); + $command->execute(); + + $rows=$builder->dbConnection->createCommand('SELECT * FROM '.$builder->dbConnection->quoteTableName($tableName))->queryAll(); + + $this->assertEquals(count($data),count($rows),'Records count miss matches!'); + foreach($rows as $rowIndex=>$row) + foreach($row as $columnName=>$value) + { + $columnIndex=array_search($columnName,$data[$rowIndex],true); + if($columnIndex==false) + continue; + $expectedValue=$data[$rowIndex][$columnIndex]; + $this->assertTrue($expectedValue==$value,"Value for column '{$columnName}' incorrect!"); + } + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommandTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommandTest.php new file mode 100644 index 0000000..6320c50 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbCommandTest.php @@ -0,0 +1,255 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + } + + public function tearDown() + { + $this->_connection->active=false; + } + + public function testGetText() + { + $sql='SELECT * FROM posts'; + $command=$this->_connection->createCommand($sql); + $this->assertEquals($command->text,$sql); + } + + public function testSetText() + { + $sql='SELECT title FROM posts'; + $command=$this->_connection->createCommand($sql); + $this->assertEquals($command->queryScalar(),'post 1'); + + $newSql='SELECT id FROM posts'; + $command->text=$newSql; + $this->assertEquals($command->text,$newSql); + $this->assertEquals($command->queryScalar(),1); + } + + public function testConnection() + { + $sql='SELECT title FROM posts'; + $command=$this->_connection->createCommand($sql); + $this->assertEquals($command->connection,$this->_connection); + } + + public function testPrepare() + { + $sql='SELECT title FROM posts'; + $command=$this->_connection->createCommand($sql); + $this->assertEquals($command->pdoStatement,null); + $command->prepare(); + $this->assertTrue($command->pdoStatement instanceof PDOStatement); + $this->assertEquals($command->queryScalar(),'post 1'); + + $command->text='Bad SQL'; + $this->setExpectedException('CException'); + $command->prepare(); + } + + public function testCancel() + { + $sql='SELECT title FROM posts'; + $command=$this->_connection->createCommand($sql); + $command->prepare(); + $this->assertTrue($command->pdoStatement instanceof PDOStatement); + $command->cancel(); + $this->assertEquals($command->pdoStatement,null); + } + + public function testExecute() + { + $sql='INSERT INTO comments(content,post_id,author_id) VALUES (\'test comment\', 1, 1)'; + $command=$this->_connection->createCommand($sql); + $this->assertEquals($command->execute(),1); + $this->assertEquals($command->execute(),1); + $command=$this->_connection->createCommand('SELECT * FROM comments WHERE content=\'test comment\''); + $this->assertEquals($command->execute(),0); + $command=$this->_connection->createCommand('SELECT COUNT(*) FROM comments WHERE content=\'test comment\''); + $this->assertEquals($command->queryScalar(),2); + + $command=$this->_connection->createCommand('bad SQL'); + $this->setExpectedException('CException'); + $command->execute(); + } + + public function testQuery() + { + $sql='SELECT * FROM posts'; + $reader=$this->_connection->createCommand($sql)->query(); + $this->assertTrue($reader instanceof CDbDataReader); + + $sql='SELECT * FROM posts'; + $command=$this->_connection->createCommand($sql); + $command->prepare(); + $reader=$command->query(); + $this->assertTrue($reader instanceof CDbDataReader); + + $command=$this->_connection->createCommand('bad SQL'); + $this->setExpectedException('CException'); + $command->query(); + } + + public function testBindParam() + { + $sql='INSERT INTO posts(title,create_time,author_id) VALUES (:title, :create_time, 1)'; + $command=$this->_connection->createCommand($sql); + $title='test title'; + $createTime=time(); + $command->bindParam(':title',$title); + $command->bindParam(':create_time',$createTime); + $command->execute(); + + $sql='SELECT create_time FROM posts WHERE title=:title'; + $command=$this->_connection->createCommand($sql); + $command->bindParam(':title',$title); + $this->assertEquals($command->queryScalar(),$createTime); + + $sql='INSERT INTO types (int_col, char_col, float_col, blob_col, numeric_col, bool_col) VALUES (:int_col, :char_col, :float_col, :blob_col, :numeric_col, :bool_col)'; + $command=$this->_connection->createCommand($sql); + $intCol=123; + $charCol='abc'; + $floatCol=1.23; + $blobCol="\x10\x11\x12"; + $numericCol='1.23'; + $boolCol=false; + $command->bindParam(':int_col',$intCol); + $command->bindParam(':char_col',$charCol); + $command->bindParam(':float_col',$floatCol); + $command->bindParam(':blob_col',$blobCol); + $command->bindParam(':numeric_col',$numericCol); + $command->bindParam(':bool_col',$boolCol); + $this->assertEquals(1,$command->execute()); + + $sql='SELECT * FROM types'; + $row=$this->_connection->createCommand($sql)->queryRow(); + $this->assertEquals($row['int_col'],$intCol); + $this->assertEquals($row['char_col'],$charCol); + $this->assertEquals($row['float_col'],$floatCol); + $this->assertEquals($row['blob_col'],$blobCol); + $this->assertEquals($row['numeric_col'],$numericCol); + } + + public function testBindValue() + { + $sql='INSERT INTO comments(content,post_id,author_id) VALUES (:content, 1, 1)'; + $command=$this->_connection->createCommand($sql); + $command->bindValue(':content','test comment'); + $command->execute(); + + $sql='SELECT post_id FROM comments WHERE content=:content'; + $command=$this->_connection->createCommand($sql); + $command->bindValue(':content','test comment'); + $this->assertEquals($command->queryScalar(),1); + } + + public function testQueryAll() + { + $rows=$this->_connection->createCommand('SELECT * FROM posts')->queryAll(); + $this->assertEquals(count($rows),5); + $row=$rows[2]; + $this->assertEquals($row['id'],3); + $this->assertEquals($row['title'],'post 3'); + + $rows=$this->_connection->createCommand('SELECT * FROM posts WHERE id=10')->queryAll(); + $this->assertEquals($rows,array()); + } + + public function testQueryRow() + { + $sql='SELECT * FROM posts'; + $row=$this->_connection->createCommand($sql)->queryRow(); + $this->assertEquals($row['id'],1); + $this->assertEquals($row['title'],'post 1'); + + $sql='SELECT * FROM posts'; + $command=$this->_connection->createCommand($sql); + $command->prepare(); + $row=$command->queryRow(); + $this->assertEquals($row['id'],1); + $this->assertEquals($row['title'],'post 1'); + + $sql='SELECT * FROM posts WHERE id=10'; + $command=$this->_connection->createCommand($sql); + $this->assertFalse($command->queryRow()); + + $command=$this->_connection->createCommand('bad SQL'); + $this->setExpectedException('CException'); + $command->queryRow(); + } + + public function testQueryColumn() + { + $sql='SELECT * FROM posts'; + $column=$this->_connection->createCommand($sql)->queryColumn(); + $this->assertEquals($column,range(1,5)); + + $command=$this->_connection->createCommand('SELECT id FROM posts WHERE id=10'); + $this->assertEquals($command->queryColumn(),array()); + + $command=$this->_connection->createCommand('bad SQL'); + $this->setExpectedException('CException'); + $command->queryColumn(); + } + + public function testQueryScalar() + { + $sql='SELECT * FROM posts'; + $this->assertEquals($this->_connection->createCommand($sql)->queryScalar(),1); + + $sql='SELECT id FROM posts'; + $command=$this->_connection->createCommand($sql); + $command->prepare(); + $this->assertEquals($command->queryScalar(),1); + + $command=$this->_connection->createCommand('SELECT id FROM posts WHERE id=10'); + $this->assertFalse($command->queryScalar()); + + $command=$this->_connection->createCommand('bad SQL'); + $this->setExpectedException('CException'); + $command->queryScalar(); + } + + public function testFetchModeDefault() + { + $sql='SELECT * FROM posts'; + $command=$this->_connection->createCommand($sql); + $result = $command->queryRow(); + $this->assertTrue(is_array($result)); + } + + public function testFetchModeObject() + { + $sql='SELECT * FROM posts'; + $command=$this->_connection->createCommand($sql); + $command->setFetchMode(PDO::FETCH_OBJ); + $result = $command->queryRow(); + $this->assertTrue(is_object($result)); + } + + public function testFetchModeClass() + { + $sql='SELECT * FROM posts'; + $command=$this->_connection->createCommand($sql); + $command->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'TestClass'); + $result = $command->queryRow(); + $this->assertTrue($result instanceof TestClass); + } +} + +class TestClass {} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbConnectionTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbConnectionTest.php new file mode 100644 index 0000000..55ed3e0 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbConnectionTest.php @@ -0,0 +1,112 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + } + + public function tearDown() + { + $this->_connection->active=false; + } + + public function testAutoConnect() + { + $db=new CDbConnection; + $db->connectionString='sqlite::memory:'; + $this->assertFalse($db->active); + $this->assertTrue($db->autoConnect); + $db->init(); + $this->assertTrue($db->active); + + $db2=new CDbConnection; + $db2->connectionString='sqlite::memory:'; + $db2->autoConnect=false; + $this->assertFalse($db2->autoConnect); + $this->assertFalse($db2->active); + $db->init(); + $this->assertFalse($db2->active); + } + + public function testInitialized() + { + $db=new CDbConnection; + $db->autoConnect=false; + $this->assertFalse($db->isInitialized); + $db->init(); + $this->assertTrue($db->isInitialized); + } + + public function testActive() + { + $this->assertFalse($this->_connection->active); + $this->_connection->active=true; + $this->assertTrue($this->_connection->active); + $pdo=$this->_connection->pdoInstance; + $this->assertTrue($pdo instanceof PDO); + + $this->_connection->active=true; + $this->assertEquals($pdo,$this->_connection->pdoInstance); + + $this->_connection->active=false; + $this->assertFalse($this->_connection->active); + $this->assertEquals($this->_connection->pdoInstance,null); + + $connection=new CDbConnection('unknown::memory:'); + $this->setExpectedException('CException'); + $connection->active=true; + } + + public function testCreateCommand() + { + $sql='SELECT * FROM posts'; + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + $command=$this->_connection->createCommand($sql); + $this->assertTrue($command instanceof CDbCommand); + } + + public function testLastInsertID() + { + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + $sql='INSERT INTO posts(title,create_time,author_id) VALUES(\'test post\',11000,1)'; + $this->_connection->createCommand($sql)->execute(); + $this->assertEquals($this->_connection->lastInsertID,6); + } + + public function testQuoteValue() + { + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + $str="this is 'my' name"; + $expectedStr="'this is ''my'' name'"; + $this->assertEquals($expectedStr,$this->_connection->quoteValue($str)); + } + + public function testColumnNameCase() + { + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + $this->assertEquals(PDO::CASE_NATURAL,$this->_connection->ColumnCase); + $this->_connection->columnCase=PDO::CASE_LOWER; + $this->assertEquals(PDO::CASE_LOWER,$this->_connection->ColumnCase); + } + + public function testNullConversion() + { + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + $this->assertEquals(PDO::NULL_NATURAL,$this->_connection->NullConversion); + $this->_connection->nullConversion=PDO::NULL_EMPTY_STRING; + $this->assertEquals(PDO::NULL_EMPTY_STRING,$this->_connection->NullConversion); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbDataReaderTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbDataReaderTest.php new file mode 100644 index 0000000..fd48d4c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbDataReaderTest.php @@ -0,0 +1,162 @@ +param1=$param1; + $this->param2=$param2; + } + + public function getTitle() + { + return $this->_title; + } + + public function setTitle($value) + { + $this->_title=$value; + } +} + +class CDbDataReaderTest extends CTestCase +{ + private $_connection; + + public function setUp() + { + if(!extension_loaded('pdo') || !extension_loaded('pdo_sqlite')) + $this->markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + } + + public function tearDown() + { + $this->_connection->active=false; + } + + public function testRead() + { + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + for($i=1;$i<=5;++$i) + { + $row=$reader->read(); + $this->assertEquals($row['id'],$i); + } + $this->assertFalse($reader->read()); + } + + public function testReadColumn() + { + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + $this->assertEquals($reader->readColumn(0),1); + $this->assertEquals($reader->readColumn(1),'post 2'); + $reader->readColumn(0); + $reader->readColumn(0); + $this->assertEquals($reader->readColumn(0),5); + $this->assertFalse($reader->readColumn(0)); + } + + public function testReadObject() + { + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + $object=$reader->readObject('PostRecord',array(null,'v2')); + $this->assertEquals($object->id,1); + $this->assertEquals($object->title,'post 1'); + $this->assertEquals($object->param1,null); + $this->assertEquals($object->param2,'v2'); + } + + public function testReadAll() + { + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + $rows=$reader->readAll(); + $this->assertEquals(count($rows),5); + $row=$rows[2]; + $this->assertEquals($row['id'],3); + $this->assertEquals($row['title'],'post 3'); + + $reader=$this->_connection->createCommand('SELECT * FROM posts WHERE id=10')->query(); + $this->assertEquals($reader->readAll(),array()); + } + + public function testClose() + { + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + $row=$reader->read(); + $row=$reader->read(); + $this->assertFalse($reader->isClosed); + $reader->close(); + $this->assertTrue($reader->isClosed); + } + + public function testRowCount() + { + // unable to test because SQLite doesn't support row count + } + + public function testColumnCount() + { + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + $this->assertEquals($reader->columnCount,5); + + $reader=$this->_connection->createCommand('SELECT * FROM posts WHERE id=11')->query(); + $this->assertEquals($reader->ColumnCount,5); + } + + public function testForeach() + { + $ids=array(); + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + foreach($reader as $row) + $ids[]=$row['id']; + $this->assertEquals(count($ids),5); + $this->assertEquals($ids[3],4); + + $this->setExpectedException('CException'); + foreach($reader as $row) + $ids[]=$row['id']; + } + + public function testFetchMode() + { + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + + $reader->fetchMode=PDO::FETCH_NUM; + $row=$reader->read(); + $this->assertFalse(isset($row['id'])); + $this->assertTrue(isset($row[0])); + + $reader->fetchMode=PDO::FETCH_ASSOC; + $row=$reader->read(); + $this->assertTrue(isset($row['id'])); + $this->assertFalse(isset($row[0])); + } + + public function testBindColumn() + { + $reader=$this->_connection->createCommand('SELECT * FROM posts')->query(); + $reader->bindColumn(1,$id); + $reader->bindColumn(2,$title); + $reader->read(); + $this->assertEquals($id,1); + $this->assertEquals($title,'post 1'); + $reader->read(); + $this->assertEquals($id,2); + $this->assertEquals($title,'post 2'); + } +} + diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbTransactionTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbTransactionTest.php new file mode 100644 index 0000000..bd63dd3 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/CDbTransactionTest.php @@ -0,0 +1,63 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/data/sqlite.sql')); + } + + public function tearDown() + { + $this->_connection->active=false; + } + + public function testBeginTransaction() + { + $sql='INSERT INTO posts(id,title,create_time,author_id) VALUES(10,\'test post\',11000,1)'; + $transaction=$this->_connection->beginTransaction(); + try + { + $this->_connection->createCommand($sql)->execute(); + $this->_connection->createCommand($sql)->execute(); + $this->fail('Expected exception not raised'); + $transaction->commit(); + } + catch(Exception $e) + { + $transaction->rollback(); + $reader=$this->_connection->createCommand('SELECT * FROM posts WHERE id=10')->query(); + $this->assertFalse($reader->read()); + } + } + + public function testCommit() + { + $sql='INSERT INTO posts(id,title,create_time,author_id) VALUES(10,\'test post\',11000,1)'; + $transaction=$this->_connection->beginTransaction(); + try + { + $this->_connection->createCommand($sql)->execute(); + $this->assertTrue($transaction->active); + $transaction->commit(); + $this->assertFalse($transaction->active); + } + catch(Exception $e) + { + $transaction->rollback(); + $this->fail('Unexpected exception'); + } + $n=$this->_connection->createCommand('SELECT COUNT(*) FROM posts WHERE id=10')->queryScalar(); + $this->assertEquals($n,1); + } +} + diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecord2Test.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecord2Test.php new file mode 100644 index 0000000..9213838 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecord2Test.php @@ -0,0 +1,626 @@ +markTestSkipped('PDO and PostgreSQL extensions are required.'); + + $this->db=new CDbConnection('pgsql:host=127.0.0.1;dbname=yii','test','test'); + try + { + $this->db->active=true; + } + catch(Exception $e) + { + $schemaFile=realpath(dirname(__FILE__).'/../data/postgres.sql'); + $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for PostgreSQL test case."); + } + + try { $this->db->createCommand('DROP SCHEMA test CASCADE')->execute(); } catch(Exception $e) { } + try { $this->db->createCommand('DROP TABLE yii_types CASCADE')->execute(); } catch(Exception $e) { } + + $sqls=file_get_contents(dirname(__FILE__).'/../data/postgres.sql'); + foreach(explode(';',$sqls) as $sql) + { + if(trim($sql)!=='') + $this->db->createCommand($sql)->execute(); + } + $this->db->active=false; + + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'db'=>array( + 'class'=>'system.db.CDbConnection', + 'connectionString'=>'pgsql:host=127.0.0.1;dbname=yii', + 'username'=>'test', + 'password'=>'test', + ), + ), + ); + $app=new TestApplication($config); + $app->db->active=true; + CActiveRecord::$db=$this->db=$app->db; + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testModel() + { + $model=Post2::model(); + $this->assertTrue($model instanceof Post2); + $this->assertTrue($model->dbConnection===$this->db); + $this->assertTrue($model->dbConnection->active); + $this->assertEquals('test.posts',$model->tableName()); + $this->assertEquals('id',$model->tableSchema->primaryKey); + $this->assertEquals('test.posts_id_seq',$model->tableSchema->sequenceName); + $this->assertEquals(array(),$model->attributeLabels()); + $this->assertEquals('Id',$model->getAttributeLabel('id')); + $this->assertEquals('Author Id',$model->getAttributeLabel('author_id')); + $this->assertTrue($model->getActiveRelation('author') instanceof CBelongsToRelation); + $this->assertTrue($model->tableSchema instanceof CDbTableSchema); + $this->assertTrue($model->commandBuilder instanceof CDbCommandBuilder); + $this->assertTrue($model->hasAttribute('id')); + $this->assertFalse($model->hasAttribute('comments')); + $this->assertFalse($model->hasAttribute('foo')); + $this->assertEquals(array(),$model->getAttributes(false)); + + $post=new Post2; + $this->assertNull($post->id); + $this->assertNull($post->title); + $post->setAttributes(array('id'=>3,'title'=>'test title')); + $this->assertNull($post->id); + $this->assertEquals('test title',$post->title); + } + + public function testFind() + { + // test find() with various parameters + $post=Post2::model()->find(); + $this->assertTrue($post instanceof Post2); + $this->assertEquals(1,$post->id); + + $post=Post2::model()->find('id=5'); + $this->assertTrue($post instanceof Post2); + $this->assertEquals(5,$post->id); + + $post=Post2::model()->find('id=:id',array(':id'=>2)); + $this->assertTrue($post instanceof Post2); + $this->assertEquals(2,$post->id); + + $post=Post2::model()->find(array('condition'=>'id=:id','params'=>array(':id'=>3))); + $this->assertTrue($post instanceof Post2); + $this->assertEquals(3,$post->id); + + // test find() without result + $post=Post2::model()->find('id=6'); + $this->assertNull($post); + + // test findAll() with various parameters + $posts=Post2::model()->findAll(); + $this->assertEquals(5,count($posts)); + $this->assertTrue($posts[3] instanceof Post2); + $this->assertEquals(4,$posts[3]->id); + + $posts=Post2::model()->findAll(new CDbCriteria(array('limit'=>3,'offset'=>1))); + $this->assertEquals(3,count($posts)); + $this->assertTrue($posts[2] instanceof Post2); + $this->assertEquals(4,$posts[2]->id); + + // test findAll() without result + $posts=Post2::model()->findAll('id=6'); + $this->assertTrue($posts===array()); + + // test findByPk + $post=Post2::model()->findByPk(2); + $this->assertEquals(2,$post->id); + + $post=Post2::model()->findByPk(array(3,2)); + $this->assertEquals(2,$post->id); + + $post=Post2::model()->findByPk(array()); + $this->assertNull($post); + + $post=Post2::model()->findByPk(6); + $this->assertNull($post); + + // test findAllByPk + $posts=Post2::model()->findAllByPk(2); + $this->assertEquals(1,count($posts)); + $this->assertEquals(2,$posts[0]->id); + + $posts=Post2::model()->findAllByPk(array(4,3,2),'id<4'); + $this->assertEquals(2,count($posts)); + $this->assertEquals(2,$posts[0]->id); + $this->assertEquals(3,$posts[1]->id); + + $posts=Post2::model()->findAllByPk(array()); + $this->assertTrue($posts===array()); + + // test findByAttributes + $post=Post2::model()->findByAttributes(array('author_id'=>2),array('order'=>'id DESC')); + $this->assertEquals(4,$post->id); + + // test findAllByAttributes + $posts=Post2::model()->findAllByAttributes(array('author_id'=>2)); + $this->assertEquals(3,count($posts)); + + // test findBySql + $post=Post2::model()->findBySql('select * from test.posts where id=:id',array(':id'=>2)); + $this->assertEquals(2,$post->id); + + // test findAllBySql + $posts=Post2::model()->findAllBySql('select * from test.posts where id>:id',array(':id'=>2)); + $this->assertEquals(3,count($posts)); + + // test count + $this->assertEquals(5,Post2::model()->count()); + $this->assertEquals(3,Post2::model()->count(array('condition'=>'id>2'))); + + // test countBySql + $this->assertEquals(1,Post2::model()->countBySql('select id from test.posts limit 1')); + + // test exists + $this->assertTrue(Post2::model()->exists('id=:id',array(':id'=>1))); + $this->assertFalse(Post2::model()->exists('id=:id',array(':id'=>6))); + } + + public function testInsert() + { + $post=new Post2; + $this->assertEquals(array(),$post->getAttributes(false)); + $post->title='test post 1'; + $post->create_time='2004-10-19 10:23:54'; + $post->author_id=1; + $post->content='test post content 1'; + $this->assertTrue($post->isNewRecord); + $this->assertNull($post->id); + $this->assertTrue($post->save()); + $this->assertEquals(array( + 'id'=>6, + 'title'=>'test post 1', + 'create_time'=>$post->create_time, + 'author_id'=>1, + 'content'=>'test post content 1'),$post->getAttributes()); + $this->assertFalse($post->isNewRecord); + $this->assertEquals($post->getAttributes(false),Post2::model()->findByPk($post->id)->getAttributes(false)); + } + + public function testUpdate() + { + // test save + $post=Post2::model()->findByPk(1); + $this->assertFalse($post->isNewRecord); + $this->assertEquals('post 1',$post->title); + $post->title='test post 1'; + $this->assertTrue($post->save()); + $this->assertFalse($post->isNewRecord); + $this->assertEquals('test post 1',$post->title); + $this->assertEquals('test post 1',Post2::model()->findByPk(1)->title); + + // test updateByPk + $this->assertEquals(2,Post2::model()->updateByPk(array(4,5),array('title'=>'test post'))); + $this->assertEquals('post 2',Post2::model()->findByPk(2)->title); + $this->assertEquals('test post',Post2::model()->findByPk(4)->title); + $this->assertEquals('test post',Post2::model()->findByPk(5)->title); + + // test updateAll + $this->assertEquals(1,Post2::model()->updateAll(array('title'=>'test post'),'id=1')); + $this->assertEquals('test post',Post2::model()->findByPk(1)->title); + + // test updateCounters + $this->assertEquals(2,Post2::model()->findByPk(2)->author_id); + $this->assertEquals(2,Post2::model()->findByPk(3)->author_id); + $this->assertEquals(2,Post2::model()->findByPk(4)->author_id); + $this->assertEquals(3,Post2::model()->updateCounters(array('author_id'=>-1),'id>2')); + $this->assertEquals(2,Post2::model()->findByPk(2)->author_id); + $this->assertEquals(1,Post2::model()->findByPk(3)->author_id); + $this->assertEquals(1,Post2::model()->findByPk(4)->author_id); + $this->assertEquals(2,Post2::model()->findByPk(5)->author_id); + } + + public function testDelete() + { + $post=Post2::model()->findByPk(1); + $this->assertTrue($post->delete()); + $this->assertNull(Post2::model()->findByPk(1)); + + $this->assertTrue(Post2::model()->findByPk(2) instanceof Post2); + $this->assertTrue(Post2::model()->findByPk(3) instanceof Post2); + $this->assertEquals(2,Post2::model()->deleteByPk(array(2,3))); + $this->assertNull(Post2::model()->findByPk(2)); + $this->assertNull(Post2::model()->findByPk(3)); + + $this->assertTrue(Post2::model()->findByPk(5) instanceof Post2); + $this->assertEquals(1,Post2::model()->deleteAll('id=5')); + $this->assertNull(Post2::model()->findByPk(5)); + } + + public function testRefresh() + { + $post=Post2::model()->findByPk(1); + $post2=Post2::model()->findByPk(1); + $post2->title='new post'; + $post2->save(); + $this->assertEquals('post 1',$post->title); + $this->assertTrue($post->refresh()); + $this->assertEquals('new post',$post->title); + } + + public function testEquals() + { + $post=Post2::model()->findByPk(1); + $post2=Post2::model()->findByPk(1); + $post3=Post2::model()->findByPk(3); + $this->assertEquals(1,$post->primaryKey); + $this->assertTrue($post->equals($post2)); + $this->assertTrue($post2->equals($post)); + $this->assertFalse($post->equals($post3)); + $this->assertFalse($post3->equals($post)); + } + + public function testValidation() + { + $user=new User2; + $user->password='passtest'; + $this->assertFalse($user->hasErrors()); + $this->assertEquals(array(),$user->errors); + $this->assertEquals(array(),$user->getErrors('username')); + $this->assertFalse($user->save()); + $this->assertNull($user->id); + $this->assertTrue($user->isNewRecord); + $this->assertTrue($user->hasErrors()); + $this->assertTrue($user->hasErrors('username')); + $this->assertTrue($user->hasErrors('email')); + $this->assertFalse($user->hasErrors('password')); + $this->assertEquals(1,count($user->getErrors('username'))); + $this->assertEquals(1,count($user->getErrors('email'))); + $this->assertEquals(2,count($user->errors)); + + $user->clearErrors(); + $this->assertFalse($user->hasErrors()); + $this->assertEquals(array(),$user->errors); + } + + public function testCompositeKey() + { + $order=new Order2; + $this->assertEquals(array('key1','key2'),$order->tableSchema->primaryKey); + $order=Order2::model()->findByPk(array('key1'=>2,'key2'=>1)); + $this->assertEquals('order 21',$order->name); + $orders=Order2::model()->findAllByPk(array(array('key1'=>2,'key2'=>1),array('key1'=>1,'key2'=>3))); + $this->assertEquals('order 13',$orders[0]->name); + $this->assertEquals('order 21',$orders[1]->name); + } + + public function testDefault() + { + $type=new ComplexType2; + $this->assertEquals(1,$type->int_col2); + $this->assertEquals('something',$type->char_col2); + $this->assertEquals(1.23,$type->real_col); + $this->assertNull($type->numeric_col); + $this->assertNull($type->time); + $this->assertNull($type->bool_col); + $this->assertTrue($type->bool_col2); + } + + public function testPublicAttribute() + { + $post=new PostExt2; + $this->assertEquals(array('id'=>null,'title'=>'default title'),$post->getAttributes(false)); + $post=Post2::model()->findByPk(1); + $this->assertEquals(array( + 'id'=>1, + 'title'=>'post 1', + 'create_time'=>'2004-10-19 10:23:54', + 'author_id'=>1, + 'content'=>'content 1'),$post->getAttributes(false)); + + $post=new PostExt2; + $post->title='test post'; + $post->create_time='2004-10-19 10:23:53'; + $post->author_id=1; + $post->content='test'; + $post->save(); + $this->assertEquals(array( + 'id'=>6, + 'title'=>'test post', + 'create_time'=>'2004-10-19 10:23:53', + 'author_id'=>1, + 'content'=>'test'),$post->getAttributes(false)); + } + + public function testLazyRelation() + { + // test belongsTo + $post=Post2::model()->findByPk(2); + $this->assertTrue($post->author instanceof User2); + $this->assertEquals(array( + 'id'=>2, + 'username'=>'user2', + 'password'=>'pass2', + 'email'=>'email2'),$post->author->getAttributes(false)); + + // test hasOne + $post=Post2::model()->findByPk(2); + $this->assertTrue($post->firstComment instanceof Comment2); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->firstComment->getAttributes(false)); + $post=Post2::model()->findByPk(4); + $this->assertNull($post->firstComment); + + // test hasMany + $post=Post2::model()->findByPk(2); + $this->assertEquals(2,count($post->comments)); + $this->assertEquals(array( + 'id'=>5, + 'content'=>'comment 5', + 'post_id'=>2, + 'author_id'=>2),$post->comments[0]->getAttributes(false)); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->comments[1]->getAttributes(false)); + $post=Post2::model()->findByPk(4); + $this->assertEquals(array(),$post->comments); + + // test manyMany + $post=Post2::model()->findByPk(2); + $this->assertEquals(2,count($post->categories)); + + // TODO: when joining, need to replace both placeholders for the two joinin tables + $this->assertEquals(array( + 'id'=>4, + 'name'=>'cat 4', + 'parent_id'=>1),$post->categories[0]->getAttributes(false)); + $this->assertEquals(array( + 'id'=>1, + 'name'=>'cat 1', + 'parent_id'=>null),$post->categories[1]->getAttributes(false)); + + + $post=Post2::model()->findByPk(4); + $this->assertEquals(array(),$post->categories); + + // test self join + $category=Category2::model()->findByPk(5); + $this->assertEquals(array(),$category->posts); + $this->assertEquals(2,count($category->children)); + $this->assertEquals(array( + 'id'=>6, + 'name'=>'cat 6', + 'parent_id'=>5),$category->children[0]->getAttributes(false)); + $this->assertEquals(array( + 'id'=>7, + 'name'=>'cat 7', + 'parent_id'=>5),$category->children[1]->getAttributes(false)); + $this->assertTrue($category->parent instanceof Category2); + $this->assertEquals(array( + 'id'=>1, + 'name'=>'cat 1', + 'parent_id'=>null),$category->parent->getAttributes(false)); + + $category=Category2::model()->findByPk(2); + $this->assertEquals(1,count($category->posts)); + $this->assertEquals(array(),$category->children); + $this->assertNull($category->parent); + + // test composite key + $order=Order2::model()->findByPk(array('key1'=>1,'key2'=>2)); + $this->assertEquals(2,count($order->items)); + $order=Order2::model()->findByPk(array('key1'=>2,'key2'=>1)); + $this->assertEquals(0,count($order->items)); + $item=Item2::model()->findByPk(4); + $this->assertTrue($item->order instanceof Order2); + $this->assertEquals(array( + 'key1'=>2, + 'key2'=>2, + 'name'=>'order 22'),$item->order->getAttributes(false)); + } + + public function testEagerRelation() + { + $post=Post2::model()->with('author','firstComment','comments','categories')->findByPk(2); + $this->assertEquals(array( + 'id'=>2, + 'username'=>'user2', + 'password'=>'pass2', + 'email'=>'email2'),$post->author->getAttributes(false)); + $this->assertTrue($post->firstComment instanceof Comment2); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->firstComment->getAttributes(false)); + $this->assertEquals(2,count($post->comments)); + $this->assertEquals(array( + 'id'=>5, + 'content'=>'comment 5', + 'post_id'=>2, + 'author_id'=>2),$post->comments[0]->getAttributes(false)); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->comments[1]->getAttributes(false)); + $this->assertEquals(2,count($post->categories)); + + $this->assertEquals(array( + 'id'=>4, + 'name'=>'cat 4', + 'parent_id'=>1),$post->categories[0]->getAttributes(false)); + $this->assertEquals(array( + 'id'=>1, + 'name'=>'cat 1', + 'parent_id'=>null),$post->categories[1]->getAttributes(false)); + + $post=Post2::model()->with('author','firstComment','comments','categories')->findByPk(4); + $this->assertEquals(array( + 'id'=>2, + 'username'=>'user2', + 'password'=>'pass2', + 'email'=>'email2'),$post->author->getAttributes(false)); + $this->assertNull($post->firstComment); + $this->assertEquals(array(),$post->comments); + $this->assertEquals(array(),$post->categories); + } + + public function testLazyRecursiveRelation() + { + $post=PostExt2::model()->findByPk(2); + $this->assertEquals(2,count($post->comments)); + $this->assertTrue($post->comments[0]->post instanceof Post2); + $this->assertTrue($post->comments[1]->post instanceof Post2); + $this->assertTrue($post->comments[0]->author instanceof User2); + $this->assertTrue($post->comments[1]->author instanceof User2); + $this->assertEquals(3,count($post->comments[0]->author->posts)); + $this->assertEquals(3,count($post->comments[1]->author->posts)); + $this->assertTrue($post->comments[0]->author->posts[1]->author instanceof User2); + + // test self join + $category=Category2::model()->findByPk(1); + $this->assertEquals(2,count($category->nodes)); + $this->assertTrue($category->nodes[0]->parent instanceof Category2); + $this->assertTrue($category->nodes[1]->parent instanceof Category2); + $this->assertEquals(2,count($category->nodes[0]->children)); // row in test.categories with id 5 (has 2 descendants) + $this->assertEquals(0,count($category->nodes[1]->children)); // row in test.categories with id 4 (has 0 descendants) + } + + public function testEagerRecursiveRelation() + { + $post=Post2::model()->with(array('comments'=>'author','categories'))->findByPk(2); + $this->assertEquals(2,count($post->comments)); + $this->assertEquals(2,count($post->categories)); + } + + public function testRelationWithCondition() + { + $posts=Post2::model()->with('comments')->findAllByPk(array(2,3,4),array('order'=>'t.id')); + $this->assertEquals(3,count($posts)); + $this->assertEquals(2,count($posts[0]->comments)); + $this->assertEquals(4,count($posts[1]->comments)); + $this->assertEquals(0,count($posts[2]->comments)); + + $post=Post2::model()->with('comments')->findByAttributes(array('id'=>2)); + $this->assertTrue($post instanceof Post2); + $this->assertEquals(2,count($post->comments)); + $posts=Post2::model()->with('comments')->findAllByAttributes(array('id'=>2)); + $this->assertEquals(1,count($posts)); + + $post=Post2::model()->with('comments')->findBySql('select * from test.posts where id=:id',array(':id'=>2)); + $this->assertTrue($post instanceof Post2); + $posts=Post2::model()->with('comments')->findAllBySql('select * from test.posts where id=:id1 OR id=:id2',array(':id1'=>2,':id2'=>3)); + $this->assertEquals(2,count($posts)); + + $post=Post2::model()->with('comments','author')->find('t.id=:id',array(':id'=>2)); + $this->assertTrue($post instanceof Post2); + + $posts=Post2::model()->with('comments','author')->findAll(array( + 'select'=>'title', + 'condition'=>'t.id=:id', + 'limit'=>1, + 'offset'=>0, + 'order'=>'t.title', + 'params'=>array(':id'=>2))); + $this->assertTrue($posts[0] instanceof Post2); + + $posts=Post2::model()->with('comments','author')->findAll(array( + 'select'=>'title', + 'condition'=>'t.id=:id', + 'limit'=>1, + 'offset'=>2, + 'order'=>'t.title', + 'params'=>array(':id'=>2))); + $this->assertTrue($posts===array()); + } + + public function testSelfManyMany() + { + $user=User2::model()->findByPk(1); + $this->assertTrue($user instanceof User2); + $friends=$user->friends; + $this->assertEquals(count($friends),2); + $this->assertEquals($friends[0]->id,2); + $this->assertEquals($friends[1]->id,3); + + $user=User2::model()->with('friends')->findByPk(1); + $this->assertTrue($user instanceof User2); + $friends=$user->friends; + $this->assertEquals(count($friends),2); + $this->assertEquals($friends[0]->id,2); + $this->assertEquals($friends[1]->id,3); + } + + public function testRelationalCount() + { + $count=Post2::model()->with('author','firstComment','comments','categories')->count(); + $this->assertEquals(5,$count); + + $count=Post2::model()->with('author','firstComment','comments','categories')->count('t.id=4'); + $this->assertEquals(1,$count); + + $count=Post2::model()->with('author','firstComment','comments','categories')->count('t.id=14'); + $this->assertEquals(0,$count); + } + + public function testEmptyFinding() + { + $post=Post2::model()->with('author','firstComment','comments','categories')->find('t.id=100'); + $this->assertNull($post); + + $posts=Post2::model()->with('author','firstComment','comments','categories')->findAll('t.id=100'); + $this->assertTrue($posts===array()); + + $post=Post2::model()->with('author','firstComment','comments','categories')->findBySql('SELECT * FROM test.posts WHERE id=100'); + $this->assertNull($post); + + Post2::model()->with('author','firstComment','comments','categories')->findAllBySql('SELECT * FROM test.posts WHERE id=100'); + $this->assertTrue($posts===array()); + } + + /** + * @see https://github.com/yiisoft/yii/issues/2122 + */ + public function testIssue2122() + { + $user=User2::model()->findByPk(2); + $this->assertEquals(2,count($user->postsWithParam)); + $this->assertEquals('post 2',$user->postsWithParam[0]->title); + $this->assertEquals('post 3',$user->postsWithParam[1]->title); + } + + /** + * https://github.com/yiisoft/yii/issues/2336 + */ + public function testEmptyModel() + { + $post=new NullablePost2(); + $post->insert(); + + $post=new NullablePost2(); + $post->title='dummy'; + $post->insert(); + + $this->assertEquals(2,$this->db->createCommand('SELECT COUNT(*) FROM "test"."nullable_posts"')->queryScalar()); + $this->assertEquals(1,$this->db->createCommand('SELECT COUNT(*) FROM "test"."nullable_posts" WHERE LENGTH("title") > 0')->queryScalar()); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecordEventWrappersTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecordEventWrappersTest.php new file mode 100644 index 0000000..f5f12d0 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecordEventWrappersTest.php @@ -0,0 +1,560 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/../data/sqlite.sql')); + CActiveRecord::$db=$this->_connection; + + // reset models + UserWithWrappers::clearCounters(); + UserWithWrappers::setBeforeFindCriteria(null); + PostWithWrappers::clearCounters(); + PostWithWrappers::setBeforeFindCriteria(null); + CommentWithWrappers::clearCounters(); + } + + public function tearDown() + { + $this->_connection->active=false; + } + + /** + * provides different db critieras to test beforeFind criteria modification + * @return array (db critiera, expected records, column assertations) + */ + public function userCriteriaProvider() + { + return array( + array(new CDbCriteria(array('limit'=>1)), 1, array()), + array(new CDbCriteria(array('select'=>"'MisterX' AS username")), 4, array('username'=>'MisterX')), + array(new CDbCriteria(array('with'=>'posts')), 4, array()), + ); + } + + /** + * provides different db critieras to test beforeFind criteria modification + * @return array (db critiera, expected records, column assertations) + */ + public function postCriteriaProvider() + { + return array( + array('', 3, array()), + array(new CDbCriteria(array('select'=>"'changedTitle' AS title")), 3, array('title'=>'changedTitle')), + array(new CDbCriteria(array('condition'=>"title='post 2'")), 1, array()), + array(new CDbCriteria(array('with'=>'comments')), 3, array()), + array(new CDbCriteria(array('scopes'=>'rename')), 3, array('title'=>'renamed post')), + ); + } + + /** + * provides different db critieras to test beforeFind criteria modification + * @return array (db critiera, expected records, column assertations) + */ + public function postCriteriaProviderLazy() + { + return array_merge($this->postCriteriaProvider(), array( + array(new CDbCriteria(array('limit'=>1)), 1, array()), + )); + } + + /** + * Check whether criteria given by dataprovider has been applied + * @param array $records + * @param CDbCriteria $criteria + * @param integer $count + * @param array $assertations + */ + public function assertCriteriaApplied($records, $criteria, $count, $assertations) + { + $this->assertEquals($count, count($records)); + foreach($assertations as $attribute => $value) { + foreach($records as $record) { + $this->assertEquals($value, $record->{$attribute}); + } + } + if (!empty($criteria)) + { + $with = (array)$criteria->with; + foreach($with as $relation) { + foreach($records as $record) { + $this->assertTrue($record->hasRelated($relation), 'relation should have been loaded due to with in criteria'); + } + } + } + } + + /** + * tests number of calls to beforeFind() on normal find*() method call + */ + public function testBeforeFind() + { + UserWithWrappers::model()->find(); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->findByAttributes(array('username'=>'user1')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->findByPk(1); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->findBySql('SELECT * FROM users'); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->findAll(); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->findAllByAttributes(array('username'=>'user1')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->findAllByPk(1); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->findAllBySql('SELECT * FROM users'); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + // test for query with no result + $this->assertEmpty(UserWithWrappers::model()->find('1=0')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->findByAttributes(array('username'=>'notExistingUser'))); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->findByPk(1000)); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->findBySql('SELECT * FROM users WHERE 1=0')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->findAll('1=0')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->findAllByAttributes(array('username'=>'notExistingUser'))); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->findAllByPk(array(1000,1001))); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->findAllBySql('SELECT * FROM users WHERE 1=0')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + + } + + /** + * setting select in beforeFind should not effect select on stat relation + * https://github.com/yiisoft/yii/issues/1381 + */ + public function testBeforeFindStatSelect() + { + PostWithWrappers::setBeforeFindCriteria(new CDbCriteria(array( + 'select' => 'id, content', + ))); + + $user1 = UserWithWrappers::model()->findByPk(1); + $this->assertEquals(1, $user1->postCount); + + $user2 = UserWithWrappers::model()->findByPk(2); + $this->assertEquals(3, $user2->postCount); + } + + /** + * tests if criteria modification in beforeFind() applies on normal find*() method call + * @dataProvider userCriteriaProvider + */ + public function testBeforeFindCriteriaModification($criteria, $count, $assertations) + { + UserWithWrappers::setBeforeFindCriteria($criteria); + + $user = UserWithWrappers::model()->find(); + $this->assertCriteriaApplied(array($user), $criteria, 1, $assertations); + + $user = UserWithWrappers::model()->findByAttributes(array('username'=>'user1')); + $this->assertCriteriaApplied(array($user), $criteria, 1, $assertations); + + $user = UserWithWrappers::model()->findByPk(1); + $this->assertCriteriaApplied(array($user), $criteria, 1, $assertations); + + $user = UserWithWrappers::model()->findBySql('SELECT * FROM users'); + $this->assertCriteriaApplied(array($user), $criteria, 1, array()); + + $users = UserWithWrappers::model()->findAll(); + $this->assertCriteriaApplied($users, $criteria, $count, $assertations); + + $users = UserWithWrappers::model()->findAllByAttributes(array('username'=>array('user1','user2','user3','user4'))); + $this->assertCriteriaApplied($users, $criteria, $count, $assertations); + + $users = UserWithWrappers::model()->findAllByPk(array(1,2,3,4)); + $this->assertCriteriaApplied($users, $criteria, $count, $assertations); + + $users = UserWithWrappers::model()->findAllBySql('SELECT * FROM users'); + $this->assertCriteriaApplied($users, $criteria, 4, array()); + } + + /** + * tests number of calls to beforeFind() on normal find*() method call with eager loading of relations + */ + public function testBeforeFindRelationalEager() + { + UserWithWrappers::model()->with('posts.comments')->find(); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->with('posts.comments')->findByAttributes(array('username'=>'user1')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->with('posts.comments')->findByPk(1); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->with('posts.comments')->findBySql('SELECT * FROM users'); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->with('posts.comments')->findAll(); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->with('posts.comments')->findAllByAttributes(array('username'=>'user1')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->with('posts.comments')->findAllByPk(1); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + UserWithWrappers::model()->with('posts.comments')->findAllBySql('SELECT * FROM users'); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + // test for query with no result + $this->assertEmpty(UserWithWrappers::model()->with('posts.comments')->find('1=0')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->with('posts.comments')->findByAttributes(array('username'=>'notExistingUser'))); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->with('posts.comments')->findByPk(1000)); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->with('posts.comments')->findBySql('SELECT * FROM users WHERE id=1000')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->with('posts.comments')->findAll('1=0')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->with('posts.comments')->findAllByAttributes(array('username'=>'notExistingUser'))); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->with('posts.comments')->findAllByPk(array(1000, 1001))); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + + $this->assertEmpty(UserWithWrappers::model()->with('posts.comments')->findAllBySql('SELECT * FROM users WHERE 1=0')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + } + + /** + * tests if criteria modification in beforeFind() applies when model is loaded eager via relation + * @dataProvider postCriteriaProvider + */ + public function testBeforeFindRelationalEagerCriteriaModification($criteria, $count, $assertations) + { + PostWithWrappers::setBeforeFindCriteria($criteria); + + $user = UserWithWrappers::model()->with('posts.comments')->find('t.id=2'); + $this->assertTrue($user->hasRelated('posts')); + $this->assertCriteriaApplied($user->posts, $criteria, $count, $assertations); + + $user = UserWithWrappers::model()->with('posts.comments')->findByAttributes(array('username'=>'user2')); + $this->assertTrue($user->hasRelated('posts')); + $this->assertCriteriaApplied($user->posts, $criteria, $count, $assertations); + + $user = UserWithWrappers::model()->with('posts.comments')->findByPk(2); + $this->assertTrue($user->hasRelated('posts')); + $this->assertCriteriaApplied($user->posts, $criteria, $count, $assertations); + + $user = UserWithWrappers::model()->with('posts.comments')->findBySql('SELECT * FROM users WHERE id=2'); + $this->assertTrue($user->hasRelated('posts')); + $this->assertCriteriaApplied($user->posts, $criteria, $count, $assertations); + + $users = UserWithWrappers::model()->with('posts.comments')->findAll('t.id=2'); + $user = reset($users); + $this->assertTrue($user->hasRelated('posts')); + $this->assertCriteriaApplied($user->posts, $criteria, $count, $assertations); + + $users = UserWithWrappers::model()->with('posts.comments')->findAllByAttributes(array('username'=>'user2')); + $user = reset($users); + $this->assertTrue($user->hasRelated('posts')); + $this->assertCriteriaApplied($user->posts, $criteria, $count, $assertations); + + $users = UserWithWrappers::model()->with('posts.comments')->findAllByPk(2); + $user = reset($users); + $this->assertTrue($user->hasRelated('posts')); + $this->assertCriteriaApplied($user->posts, $criteria, $count, $assertations); + + $users = UserWithWrappers::model()->with('posts.comments')->findAllBySql('SELECT * FROM users WHERE id=2'); + $user = reset($users); + $this->assertTrue($user->hasRelated('posts')); + $this->assertCriteriaApplied($user->posts, $criteria, $count, $assertations); + } + + /** + * tests number of calls to beforeFind() on normal find*() method call with lazy loading of relations + */ + public function testBeforeFindRelationalLazy() + { + $user=UserWithWrappers::model()->find(); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $user->posts; + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + + $user=UserWithWrappers::model()->find(); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),1); + $user->posts(array('with'=>'comments')); + $this->assertEquals(UserWithWrappers::getCounter('beforeFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('beforeFind'),1); + $this->assertEquals(CommentWithWrappers::getCounter('beforeFind'),1); + } + + /** + * tests if criteria modification in beforeFind() applies when model is loaded lazy via relation + * @dataProvider postCriteriaProviderLazy + */ + public function testBeforeFindRelationalLazyCriteriaModification($criteria, $count, $assertations) + { + PostWithWrappers::setBeforeFindCriteria($criteria); + + $user=UserWithWrappers::model()->findByPk(2); + $posts = $user->posts; + $this->assertCriteriaApplied($posts, $criteria, $count, $assertations); + + $user=UserWithWrappers::model()->findByPk(2); + $posts = $user->posts(array('with'=>'comments')); + $this->assertCriteriaApplied($posts, $criteria, $count, $assertations); + foreach($posts as $post) { + $this->assertTrue($post->hasRelated('comments')); + } + } + + /** + * tests if criteria modification in beforeFind() does not overide scopes defined by already applied criteria + * @dataProvider postCriteriaProviderLazy + */ + public function testBeforeFindRelationalLazyCriteriaScopes($criteria, $count, $assertations) + { + PostWithWrappers::setBeforeFindCriteria($criteria); + + $user=UserWithWrappers::model()->findByPk(2); + $posts = $user->postsWithScope; + $this->assertCriteriaApplied($posts, $criteria, $count, $assertations); + foreach($posts as $post) { + $this->assertEquals('replaced content', $post->content); + } + + $user=UserWithWrappers::model()->findByPk(2); + $posts = $user->posts(array('with'=>'comments','scopes'=>array('replaceContent'))); + $this->assertCriteriaApplied($posts, $criteria, $count, $assertations); + foreach($posts as $post) { + $this->assertTrue($post->hasRelated('comments')); + $this->assertEquals('replaced content', $post->content); + } + } + + /** + * tests number of calls to afterFind() on normal find*() method call + */ + public function testAfterFind() + { + UserWithWrappers::model()->find(); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + + UserWithWrappers::model()->findByAttributes(array('username'=>'user1')); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + + UserWithWrappers::model()->findByPk(1); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + + UserWithWrappers::model()->findBySql('SELECT * FROM users'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + + UserWithWrappers::model()->findAll(); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),4); + + UserWithWrappers::model()->findAllByAttributes(array('username'=>'user1')); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + + UserWithWrappers::model()->findAllByPk(1); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + + UserWithWrappers::model()->findAllBySql('SELECT * FROM users'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),4); + + // test for query with no result + UserWithWrappers::model()->find('1=0'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->findByAttributes(array('username'=>'notExistingUser')); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->findByPk(1000); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->findBySql('SELECT * FROM users WHERE 1=0'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->findAll('1=0'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->findAllByAttributes(array('username'=>'notExistingUser')); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->findAllByPk(array(1000,1001)); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->findAllBySql('SELECT * FROM users WHERE 1=0'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + } + + /** + * tests number of calls to afterFind() on normal find*() method call with eager loding of relations + */ + public function testAfterFindRelational() + { + UserWithWrappers::model()->with('posts.comments')->find(); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),4); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),5); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),10); + + UserWithWrappers::model()->with('posts.comments')->findByAttributes(array('username'=>'user2')); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),3); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),6); + + UserWithWrappers::model()->with('posts.comments')->findByPk(2); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),3); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),6); + + UserWithWrappers::model()->with('posts.comments')->findBySql('SELECT * FROM users WHERE id=2'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),3); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),6); + + UserWithWrappers::model()->with('posts.comments')->findAll(); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),4); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),5); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),10); + + UserWithWrappers::model()->with('posts.comments')->findAllByAttributes(array('username'=>'user2')); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),3); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),6); + + UserWithWrappers::model()->with('posts.comments')->findAllByPk(2); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),3); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),6); + + UserWithWrappers::model()->with('posts.comments')->findAllBySql('SELECT * FROM users'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),4); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),5); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),10); + + // test for query with no result + UserWithWrappers::model()->with('posts.comments')->find('1=0'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->with('posts.comments')->findByAttributes(array('username'=>'notExistingUser')); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->with('posts.comments')->findByPk(1000); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->with('posts.comments')->findBySql('SELECT * FROM users WHERE id=1000'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->with('posts.comments')->findAll('1=0'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->with('posts.comments')->findAllByAttributes(array('username'=>'notExistingUser')); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->with('posts.comments')->findAllByPk(array(1000, 1001)); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),0); + + UserWithWrappers::model()->with('posts.comments')->findAllBySql('SELECT * FROM users WHERE 1=0'); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),0); + } + + /** + * CActiveRecord::getRelated doesn't call afterFind() with `through` relation + * https://github.com/yiisoft/yii/issues/591 + */ + public function testIssue591() + { + UserWithWrappers::model()->with('comments')->findByPk(1); + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),3); + + $user = UserWithWrappers::model()->findByPk(1); + $user->comments; + $this->assertEquals(UserWithWrappers::getCounter('afterFind'),1); + $this->assertEquals(PostWithWrappers::getCounter('afterFind'),0); + $this->assertEquals(CommentWithWrappers::getCounter('afterFind'),3); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecordTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecordTest.php new file mode 100644 index 0000000..ab8482f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/ar/CActiveRecordTest.php @@ -0,0 +1,1503 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/../data/sqlite.sql')); + CActiveRecord::$db=$this->_connection; + } + + protected function tearDown() + { + $this->_connection->active=false; + } + + public function testModel() + { + $model=Post::model(); + $this->assertTrue($model instanceof Post); + $this->assertTrue($model->dbConnection===$this->_connection); + $this->assertTrue($model->dbConnection->active); + $this->assertEquals('posts',$model->tableName()); + $this->assertEquals('id',$model->tableSchema->primaryKey); + $this->assertTrue($model->tableSchema->sequenceName===''); + $this->assertEquals(array(),$model->attributeLabels()); + $this->assertEquals('Id',$model->getAttributeLabel('id')); + $this->assertEquals('Author Id',$model->getAttributeLabel('author_id')); + $this->assertTrue($model->getActiveRelation('author') instanceof CBelongsToRelation); + $this->assertTrue($model->tableSchema instanceof CDbTableSchema); + $this->assertTrue($model->commandBuilder instanceof CDbCommandBuilder); + $this->assertTrue($model->hasAttribute('id')); + $this->assertFalse($model->hasAttribute('comments')); + $this->assertFalse($model->hasAttribute('foo')); + $this->assertEquals(array('id'=>null,'title'=>null,'create_time'=>null,'author_id'=>null,'content'=>null),$model->attributes); + + $post=new Post; + $this->assertNull($post->id); + $this->assertNull($post->title); + $post->setAttributes(array('id'=>3,'title'=>'test title')); + $this->assertNull($post->id); + $this->assertEquals('test title',$post->title); + } + + public function testFind() + { + // test find() with various parameters + $post=Post::model()->find(); + $this->assertTrue($post instanceof Post); + $this->assertEquals(1,$post->id); + + $post=Post::model()->find('id=5'); + $this->assertTrue($post instanceof Post); + $this->assertEquals(5,$post->id); + + $post=Post::model()->find('id=:id',array(':id'=>2)); + $this->assertTrue($post instanceof Post); + $this->assertEquals(2,$post->id); + + $post=Post::model()->find(array('condition'=>'id=:id','params'=>array(':id'=>3))); + $this->assertTrue($post instanceof Post); + $this->assertEquals(3,$post->id); + + // test find() without result + $post=Post::model()->find('id=6'); + $this->assertNull($post); + + // test findAll() with various parameters + $posts=Post::model()->findAll(); + $this->assertEquals(5,count($posts)); + $this->assertTrue($posts[3] instanceof Post); + $this->assertEquals(4,$posts[3]->id); + + $posts=Post::model()->findAll(new CDbCriteria(array('limit'=>3,'offset'=>1))); + $this->assertEquals(3,count($posts)); + $this->assertTrue($posts[2] instanceof Post); + $this->assertEquals(4,$posts[2]->id); + + // test findAll() without result + $posts=Post::model()->findAll('id=6'); + $this->assertTrue($posts===array()); + + // test findByPk + $post=Post::model()->findByPk(2); + $this->assertEquals(2,$post->id); + + $post=Post::model()->findByPk(array(3,2)); + $this->assertEquals(2,$post->id); + + $post=Post::model()->findByPk(array()); + $this->assertNull($post); + + $post=Post::model()->findByPk(null); + $this->assertNull($post); + + $post=Post::model()->findByPk(6); + $this->assertNull($post); + + // test findAllByPk + $posts=Post::model()->findAllByPk(2); + $this->assertEquals(1,count($posts)); + $this->assertEquals(2,$posts[0]->id); + + $posts=Post::model()->findAllByPk(array(4,3,2),'id<4'); + $this->assertEquals(2,count($posts)); + $this->assertEquals(2,$posts[0]->id); + $this->assertEquals(3,$posts[1]->id); + + $posts=Post::model()->findAllByPk(array()); + $this->assertTrue($posts===array()); + + // test findByAttributes + $post=Post::model()->findByAttributes(array('author_id'=>2),array('order'=>'id DESC')); + $this->assertEquals(4,$post->id); + + // test findAllByAttributes + $posts=Post::model()->findAllByAttributes(array('author_id'=>2)); + $this->assertEquals(3,count($posts)); + + // test findBySql + $post=Post::model()->findBySql('select * from posts where id=:id',array(':id'=>2)); + $this->assertEquals(2,$post->id); + + // test findAllBySql + $posts=Post::model()->findAllBySql('select * from posts where id>:id',array(':id'=>2)); + $this->assertEquals(3,count($posts)); + + // test count + $this->assertEquals(5,Post::model()->count()); + $this->assertEquals(3,Post::model()->count(array('condition'=>'id>2'))); + + // test countBySql + $this->assertEquals(1,Post::model()->countBySql('select id from posts limit 1')); + + // test exists + $this->assertTrue(Post::model()->exists('id=:id',array(':id'=>1))); + $this->assertFalse(Post::model()->exists('id=:id',array(':id'=>6))); + } + + public function testInsert() + { + $post=new Post; + $this->assertEquals(array('id'=>null,'title'=>null,'create_time'=>null,'author_id'=>null,'content'=>null),$post->attributes); + $post->title='test post 1'; + $post->create_time=time(); + $post->author_id=1; + $post->content='test post content 1'; + $this->assertTrue($post->isNewRecord); + $this->assertNull($post->id); + $this->assertTrue($post->save()); + $this->assertEquals(array( + 'id'=>6, + 'title'=>'test post 1', + 'create_time'=>$post->create_time, + 'author_id'=>1, + 'content'=>'test post content 1'),$post->attributes); + $this->assertFalse($post->isNewRecord); + $this->assertEquals($post->attributes,Post::model()->findByPk($post->id)->attributes); + } + + public function testUpdate() + { + // test save + $post=Post::model()->findByPk(1); + $this->assertFalse($post->isNewRecord); + $this->assertEquals('post 1',$post->title); + $post->title='test post 1'; + $this->assertTrue($post->save()); + $this->assertFalse($post->isNewRecord); + $this->assertEquals('test post 1',$post->title); + $this->assertEquals('test post 1',Post::model()->findByPk(1)->title); + + // test updateByPk + $this->assertEquals(2,Post::model()->updateByPk(array(4,5),array('title'=>'test post'))); + $this->assertEquals('post 2',Post::model()->findByPk(2)->title); + $this->assertEquals('test post',Post::model()->findByPk(4)->title); + $this->assertEquals('test post',Post::model()->findByPk(5)->title); + + // test updateAll + $this->assertEquals(1,Post::model()->updateAll(array('title'=>'test post'),'id=1')); + $this->assertEquals('test post',Post::model()->findByPk(1)->title); + + // test updateCounters + $this->assertEquals(2,Post::model()->findByPk(2)->author_id); + $this->assertEquals(2,Post::model()->findByPk(3)->author_id); + $this->assertEquals(2,Post::model()->findByPk(4)->author_id); + $this->assertEquals(3,Post::model()->updateCounters(array('author_id'=>-1),'id>2')); + $this->assertEquals(2,Post::model()->findByPk(2)->author_id); + $this->assertEquals(1,Post::model()->findByPk(3)->author_id); + } + + public function testSaveCounters() + { + $post=Post::model()->findByPk(2); + $this->assertEquals(2, $post->author_id); + $result=$post->saveCounters(array('author_id'=>-1)); + $this->assertTrue($result); + $this->assertEquals(1, $post->author_id); + $this->assertEquals(1, Post::model()->findByPk(2)->author_id); + $this->assertEquals(2, Post::model()->findByPk(3)->author_id); + } + + public function testDelete() + { + $post=Post::model()->findByPk(1); + $this->assertTrue($post->delete()); + $this->assertNull(Post::model()->findByPk(1)); + + $this->assertTrue(Post::model()->findByPk(2) instanceof Post); + $this->assertTrue(Post::model()->findByPk(3) instanceof Post); + $this->assertEquals(2,Post::model()->deleteByPk(array(2,3))); + $this->assertNull(Post::model()->findByPk(2)); + $this->assertNull(Post::model()->findByPk(3)); + + $this->assertTrue(Post::model()->findByPk(5) instanceof Post); + $this->assertEquals(1,Post::model()->deleteAll('id=5')); + $this->assertNull(Post::model()->findByPk(5)); + } + + public function testRefresh() + { + $post=Post::model()->findByPk(1); + $post2=Post::model()->findByPk(1); + $post2->title='new post'; + $post2->save(); + $this->assertEquals('post 1',$post->title); + $this->assertTrue($post->refresh()); + $this->assertEquals('new post',$post->title); + + $post = new Post(); + $this->assertFalse($post->refresh()); + $post->id = 1; + $this->assertTrue($post->refresh()); + $this->assertEquals('new post',$post->title); + } + + public function testEquals() + { + $post=Post::model()->findByPk(1); + $post2=Post::model()->findByPk(1); + $post3=Post::model()->findByPk(3); + $this->assertEquals(1,$post->primaryKey); + $this->assertTrue($post->equals($post2)); + $this->assertTrue($post2->equals($post)); + $this->assertFalse($post->equals($post3)); + $this->assertFalse($post3->equals($post)); + } + + public function testValidation() + { + $user=new User; + $user->password='passtest'; + $this->assertFalse($user->hasErrors()); + $this->assertEquals(array(),$user->errors); + $this->assertEquals(array(),$user->getErrors('username')); + $this->assertFalse($user->save()); + $this->assertNull($user->id); + $this->assertTrue($user->isNewRecord); + $this->assertTrue($user->hasErrors()); + $this->assertTrue($user->hasErrors('username')); + $this->assertTrue($user->hasErrors('email')); + $this->assertFalse($user->hasErrors('password')); + $this->assertEquals(1,count($user->getErrors('username'))); + $this->assertEquals(1,count($user->getErrors('email'))); + $this->assertEquals(2,count($user->errors)); + + $user->clearErrors(); + $this->assertFalse($user->hasErrors()); + $this->assertEquals(array(),$user->errors); + } + + public function testCompositeKey() + { + $order=new Order; + $this->assertEquals(array('key1','key2'),$order->tableSchema->primaryKey); + $order=Order::model()->findByPk(array('key1'=>2,'key2'=>1)); + $this->assertEquals('order 21',$order->name); + $orders=Order::model()->findAllByPk(array(array('key1'=>2,'key2'=>1),array('key1'=>1,'key2'=>3))); + $this->assertEquals('order 13',$orders[0]->name); + $this->assertEquals('order 21',$orders[1]->name); + } + + public function testDefault() + { + $type=new ComplexType; + $this->assertEquals(1,$type->int_col2); + $this->assertEquals('something',$type->char_col2); + $this->assertEquals(1.23,$type->float_col2); + $this->assertEquals(33.22,$type->numeric_col); + $this->assertEquals(123,$type->time); + $this->assertNull($type->bool_col); + $this->assertTrue($type->bool_col2); + } + + public function testPublicAttribute() + { + $post=new PostExt; + $this->assertEquals(array('id'=>null,'title'=>'default title','create_time'=>null,'author_id'=>null,'content'=>null),$post->attributes); + $post=Post::model()->findByPk(1); + $this->assertEquals(array( + 'id'=>1, + 'title'=>'post 1', + 'create_time'=>100000, + 'author_id'=>1, + 'content'=>'content 1'),$post->attributes); + + $post=new PostExt; + $post->title='test post'; + $post->create_time=1000000; + $post->author_id=1; + $post->content='test'; + $post->save(); + $this->assertEquals(array( + 'id'=>6, + 'title'=>'test post', + 'create_time'=>1000000, + 'author_id'=>1, + 'content'=>'test'),$post->attributes); + } + + public function testLazyRelation() + { + // test belongsTo + $post=Post::model()->findByPk(2); + $this->assertTrue($post->author instanceof User); + $this->assertEquals(array( + 'id'=>2, + 'username'=>'user2', + 'password'=>'pass2', + 'email'=>'email2'),$post->author->attributes); + + // test hasOne + $post=Post::model()->findByPk(2); + $this->assertTrue($post->firstComment instanceof Comment); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->firstComment->attributes); + $post=Post::model()->findByPk(4); + $this->assertNull($post->firstComment); + + // test hasMany + $post=Post::model()->findByPk(2); + $this->assertEquals(2,count($post->comments)); + $this->assertEquals(array( + 'id'=>5, + 'content'=>'comment 5', + 'post_id'=>2, + 'author_id'=>2),$post->comments[0]->attributes); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->comments[1]->attributes); + $post=Post::model()->findByPk(4); + $this->assertEquals(array(),$post->comments); + + // test manyMany + $post=Post::model()->findByPk(2); + $this->assertEquals(2,count($post->categories)); + $this->assertEquals(array( + 'id'=>4, + 'name'=>'cat 4', + 'parent_id'=>1),$post->categories[0]->attributes); + $this->assertEquals(array( + 'id'=>1, + 'name'=>'cat 1', + 'parent_id'=>null),$post->categories[1]->attributes); + $post=Post::model()->findByPk(4); + $this->assertEquals(array(),$post->categories); + + // test self join + $category=Category::model()->findByPk(5); + $this->assertEquals(array(),$category->posts); + $this->assertEquals(2,count($category->children)); + $this->assertEquals(array( + 'id'=>6, + 'name'=>'cat 6', + 'parent_id'=>5),$category->children[0]->attributes); + $this->assertEquals(array( + 'id'=>7, + 'name'=>'cat 7', + 'parent_id'=>5),$category->children[1]->attributes); + $this->assertTrue($category->parent instanceof Category); + $this->assertEquals(array( + 'id'=>1, + 'name'=>'cat 1', + 'parent_id'=>null),$category->parent->attributes); + + $category=Category::model()->findByPk(2); + $this->assertEquals(1,count($category->posts)); + $this->assertEquals(array(),$category->children); + $this->assertNull($category->parent); + + // test composite key + $order=Order::model()->findByPk(array('key1'=>1,'key2'=>2)); + $this->assertEquals(2,count($order->items)); + $order=Order::model()->findByPk(array('key1'=>2,'key2'=>1)); + $this->assertEquals(0,count($order->items)); + $item=Item::model()->findByPk(4); + $this->assertTrue($item->order instanceof Order); + $this->assertEquals(array( + 'key1'=>2, + 'key2'=>2, + 'name'=>'order 22'),$item->order->attributes); + } + + public function testEagerRelation2() + { + $post=Post::model()->with('author','firstComment','comments','categories')->findByPk(2); + } + + private function checkEagerLoadedModel($post) + { + $this->assertEquals(array( + 'id'=>2, + 'username'=>'user2', + 'password'=>'pass2', + 'email'=>'email2'),$post->author->attributes); + $this->assertTrue($post->firstComment instanceof Comment); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->firstComment->attributes); + $this->assertEquals(2,count($post->comments)); + $this->assertEquals(array( + 'id'=>5, + 'content'=>'comment 5', + 'post_id'=>2, + 'author_id'=>2),$post->comments[0]->attributes); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->comments[1]->attributes); + $this->assertEquals(2,count($post->categories)); + $this->assertEquals(array( + 'id'=>4, + 'name'=>'cat 4', + 'parent_id'=>1),$post->categories[0]->attributes); + $this->assertEquals(array( + 'id'=>1, + 'name'=>'cat 1', + 'parent_id'=>null),$post->categories[1]->attributes); + } + + public function testEagerRelation() + { + $post=Post::model()->with('author','firstComment','comments','categories')->findByPk(2); + $this->checkEagerLoadedModel($post); + $post=Post::model()->findByPk(2,array( + 'with'=>array('author','firstComment','comments','categories'), + )); + $this->checkEagerLoadedModel($post); + + $post=Post::model()->with('author','firstComment','comments','categories')->findByPk(4); + $this->assertEquals(array( + 'id'=>2, + 'username'=>'user2', + 'password'=>'pass2', + 'email'=>'email2'),$post->author->attributes); + $this->assertNull($post->firstComment); + $this->assertEquals(array(),$post->comments); + $this->assertEquals(array(),$post->categories); + } + + public function testLazyRecursiveRelation() + { + $post=PostExt::model()->findByPk(2); + $this->assertEquals(2,count($post->comments)); + $this->assertTrue($post->comments[0]->post instanceof Post); + $this->assertTrue($post->comments[1]->post instanceof Post); + $this->assertTrue($post->comments[0]->author instanceof User); + $this->assertTrue($post->comments[1]->author instanceof User); + $this->assertEquals(3,count($post->comments[0]->author->posts)); + $this->assertEquals(3,count($post->comments[1]->author->posts)); + $this->assertTrue($post->comments[0]->author->posts[1]->author instanceof User); + + // test self join + $category=Category::model()->findByPk(1); + $this->assertEquals(2,count($category->nodes)); + $this->assertTrue($category->nodes[0]->parent instanceof Category); + $this->assertTrue($category->nodes[1]->parent instanceof Category); + $this->assertEquals(0,count($category->nodes[0]->children)); + $this->assertEquals(2,count($category->nodes[1]->children)); + } + + public function testEagerRecursiveRelation() + { + //$post=Post::model()->with(array('comments'=>'author','categories'))->findByPk(2); + $post=Post::model()->with('comments.author','categories')->findByPk(2); + $this->assertEquals(2,count($post->comments)); + $this->assertEquals(2,count($post->categories)); + + $posts=PostExt::model()->with('comments')->findAll(); + $this->assertEquals(5,count($posts)); + } + + public function testRelationWithCondition() + { + $posts=Post::model()->with('comments')->findAllByPk(array(2,3,4),array('order'=>'t.id')); + $this->assertEquals(3,count($posts)); + $this->assertEquals(2,count($posts[0]->comments)); + $this->assertEquals(4,count($posts[1]->comments)); + $this->assertEquals(0,count($posts[2]->comments)); + + $post=Post::model()->with('comments')->findByAttributes(array('id'=>2)); + $this->assertTrue($post instanceof Post); + $this->assertEquals(2,count($post->comments)); + $posts=Post::model()->with('comments')->findAllByAttributes(array('id'=>2)); + $this->assertEquals(1,count($posts)); + + $post=Post::model()->with('comments')->findBySql('select * from posts where id=:id',array(':id'=>2)); + $this->assertTrue($post instanceof Post); + $posts=Post::model()->with('comments')->findAllBySql('select * from posts where id=:id1 OR id=:id2',array(':id1'=>2,':id2'=>3)); + $this->assertEquals(2,count($posts)); + + $post=Post::model()->with('comments','author')->find('t.id=:id',array(':id'=>2)); + $this->assertTrue($post instanceof Post); + + $posts=Post::model()->with('comments','author')->findAll(array( + 'select'=>'title', + 'condition'=>'t.id=:id', + 'limit'=>1, + 'offset'=>0, + 'order'=>'t.title', + 'group'=>'t.id', + 'params'=>array(':id'=>2))); + $this->assertTrue($posts[0] instanceof Post); + + $posts=Post::model()->with('comments','author')->findAll(array( + 'select'=>'title', + 'condition'=>'t.id=:id', + 'limit'=>1, + 'offset'=>2, + 'order'=>'t.title', + 'params'=>array(':id'=>2))); + $this->assertTrue($posts===array()); + } + + public function testRelationWithColumnAlias() + { + $users=User::model()->with('posts')->findAll(array( + 'select'=>'id, username AS username2', + 'order'=>'username2', + )); + + $this->assertEquals(4,count($users)); + $this->assertEquals($users[1]->username,null); + $this->assertEquals($users[1]->username2,'user2'); + } + + public function testRelationalWithoutFK() + { + $users=UserNoFk::model()->with('posts')->findAll(); + $this->assertEquals(4,count($users)); + $this->assertEquals(3,count($users[1]->posts)); + + $posts=PostNoFk::model()->with('author')->findAll(); + $this->assertEquals(5,count($posts)); + $this->assertTrue($posts[2]->author instanceof UserNoFk); + } + + public function testRelationWithNewRecord() + { + $user=new User; + $posts=$user->posts; + $this->assertTrue(is_array($posts) && empty($posts)); + + $post=new Post; + $author=$post->author; + $this->assertNull($author); + } + + public function testRelationWithDynamicCondition() + { + $user=User::model()->with('posts')->findByPk(2); + $this->assertEquals($user->posts[0]->id,2); + $this->assertEquals($user->posts[1]->id,3); + $this->assertEquals($user->posts[2]->id,4); + $user=User::model()->with(array('posts'=>array('order'=>'posts.id DESC')))->findByPk(2); + $this->assertEquals($user->posts[0]->id,4); + $this->assertEquals($user->posts[1]->id,3); + $this->assertEquals($user->posts[2]->id,2); + } + + public function testEagerTogetherRelation() + { + $post=Post::model()->with('author','firstComment','comments','categories')->findByPk(2); + $comments=$post->comments; + $this->assertEquals(array( + 'id'=>2, + 'username'=>'user2', + 'password'=>'pass2', + 'email'=>'email2'),$post->author->attributes); + $this->assertTrue($post->firstComment instanceof Comment); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->firstComment->attributes); + $this->assertEquals(2,count($post->comments)); + $this->assertEquals(array( + 'id'=>5, + 'content'=>'comment 5', + 'post_id'=>2, + 'author_id'=>2),$post->comments[0]->attributes); + $this->assertEquals(array( + 'id'=>4, + 'content'=>'comment 4', + 'post_id'=>2, + 'author_id'=>2),$post->comments[1]->attributes); + $this->assertEquals(2,count($post->categories)); + $this->assertEquals(array( + 'id'=>4, + 'name'=>'cat 4', + 'parent_id'=>1),$post->categories[0]->attributes); + $this->assertEquals(array( + 'id'=>1, + 'name'=>'cat 1', + 'parent_id'=>null),$post->categories[1]->attributes); + + $post=Post::model()->with('author','firstComment','comments','categories')->findByPk(4); + $this->assertEquals(array( + 'id'=>2, + 'username'=>'user2', + 'password'=>'pass2', + 'email'=>'email2'),$post->author->attributes); + $this->assertNull($post->firstComment); + $this->assertEquals(array(),$post->comments); + $this->assertEquals(array(),$post->categories); + } + + public function testRelationalCount() + { + $count=Post::model()->with('author','firstComment','comments','categories')->count(); + $this->assertEquals(5,$count); + + $count=Post::model()->count(array('with'=>array('author','firstComment','comments','categories'))); + $this->assertEquals(5,$count); + + $count=Post::model()->with('author','firstComment','comments','categories')->count('t.id=4'); + $this->assertEquals(1,$count); + + $count=Post::model()->with('author','firstComment','comments','categories')->count('t.id=14'); + $this->assertEquals(0,$count); + } + + public function testRelationalStat() + { + $users=User::model()->with('postCount')->findAll(); + $this->assertEquals(4,count($users)); + $this->assertEquals(1,$users[0]->postCount); + $this->assertEquals(3,$users[1]->postCount); + $this->assertEquals(1,$users[2]->postCount); + + $users=User::model()->findAll(); + $this->assertEquals(4,count($users)); + $this->assertEquals(1,$users[0]->postCount); + $this->assertEquals(3,$users[1]->postCount); + $this->assertEquals(1,$users[2]->postCount); + + $orders=Order::model()->with('itemCount')->findAll(); + $this->assertEquals(4,count($orders)); + $this->assertEquals(2,$orders[0]->itemCount); + $this->assertEquals(1,$orders[1]->itemCount); + $this->assertEquals(0,$orders[2]->itemCount); + $this->assertEquals(2,$orders[3]->itemCount); + + $orders=Order::model()->findAll(); + $this->assertEquals(4,count($orders)); + $this->assertEquals(2,$orders[0]->itemCount); + $this->assertEquals(1,$orders[1]->itemCount); + $this->assertEquals(0,$orders[2]->itemCount); + $this->assertEquals(2,$orders[3]->itemCount); + + $categories=Category::model()->with('postCount')->findAll(); + $this->assertEquals(7,count($categories)); + $this->assertEquals(3,$categories[0]->postCount); + $this->assertEquals(1,$categories[1]->postCount); + $this->assertEquals(1,$categories[2]->postCount); + $this->assertEquals(1,$categories[3]->postCount); + $this->assertEquals(0,$categories[4]->postCount); + $this->assertEquals(0,$categories[5]->postCount); + $this->assertEquals(0,$categories[6]->postCount); + + $categories=Category::model()->findAll(); + $this->assertEquals(7,count($categories)); + $this->assertEquals(3,$categories[0]->postCount); + $this->assertEquals(1,$categories[1]->postCount); + $this->assertEquals(1,$categories[2]->postCount); + $this->assertEquals(1,$categories[3]->postCount); + $this->assertEquals(0,$categories[4]->postCount); + $this->assertEquals(0,$categories[5]->postCount); + $this->assertEquals(0,$categories[6]->postCount); + + $users=User::model()->with('postCount','posts.commentCount')->findAll(); + $this->assertEquals(4,count($users)); + } + + public function testLazyLoadingWithConditions() + { + $user=User::model()->findByPk(2); + $posts=$user->posts; + $this->assertEquals(3,count($posts)); + $posts=$user->posts(array('condition'=>'posts.id>=3', 'alias'=>'posts')); + $this->assertEquals(2,count($posts)); + } + + public function testDuplicateLazyLoadingBug() + { + $user=User::model()->with(array( + 'posts'=>array('on'=>'posts.id=-1') + ))->findByPk(1); + // with the bug, an eager loading for 'posts' would be trigger in the following + // and result with non-empty posts + $this->assertTrue($user->posts===array()); + } + + public function testTogether() + { + // test without together + $users=UserNoTogether::model()->with('posts.comments')->findAll(); + $postCount=0; + $commentCount=0; + foreach($users as $user) + { + $postCount+=count($user->posts); + foreach($posts=$user->posts as $post) + $commentCount+=count($post->comments); + } + $this->assertEquals(4,count($users)); + $this->assertEquals(5,$postCount); + $this->assertEquals(10,$commentCount); + + // test with together + $users=UserNoTogether::model()->with('posts.comments')->together()->findAll(); + $postCount=0; + $commentCount=0; + foreach($users as $user) + { + $postCount+=count($user->posts); + foreach($posts=$user->posts as $post) + $commentCount+=count($post->comments); + } + $this->assertEquals(3,count($users)); + $this->assertEquals(4,$postCount); + $this->assertEquals(10,$commentCount); + } + + public function testTogetherWithOption() + { + // test with together off option + $users=User::model()->with(array( + 'posts'=>array( + 'with'=>array( + 'comments'=>array( + 'joinType'=>'INNER JOIN', + 'together'=>false, + ), + ), + 'joinType'=>'INNER JOIN', + 'together'=>false, + ), + ))->findAll(); + + $postCount=0; + $commentCount=0; + foreach($users as $user) + { + $postCount+=count($user->posts); + foreach($posts=$user->posts as $post) + $commentCount+=count($post->comments); + } + $this->assertEquals(4,count($users)); + $this->assertEquals(5,$postCount); + $this->assertEquals(10,$commentCount); + + // test with together on option + $users=User::model()->with(array( + 'posts'=>array( + 'with'=>array( + 'comments'=>array( + 'joinType'=>'INNER JOIN', + 'together'=>true, + ), + ), + 'joinType'=>'INNER JOIN', + 'together'=>true, + ), + ))->findAll(); + + $postCount=0; + $commentCount=0; + foreach($users as $user) + { + $postCount+=count($user->posts); + foreach($posts=$user->posts as $post) + $commentCount+=count($post->comments); + } + $this->assertEquals(3,count($users)); + $this->assertEquals(4,$postCount); + $this->assertEquals(10,$commentCount); + } + + public function testCountByAttributes() + { + $n=Post::model()->countByAttributes(array('author_id'=>2)); + $this->assertEquals(3,$n); + + } + + public function testScopes() + { + $models1=Post::model()->post23()->findAll(); + $models2=Post::model()->findAll(array('scopes'=>'post23')); + + foreach(array($models1,$models2) as $models) + { + $this->assertEquals(2,count($models)); + $this->assertEquals(2,$models[0]->id); + $this->assertEquals(3,$models[1]->id); + } + + $model1=Post::model()->post23()->find(); + $model2=Post::model()->find(array('scopes'=>'post23')); + + foreach(array($model1,$model2) as $model) + $this->assertEquals(2,$model->id); + + $models1=Post::model()->post23()->post3()->findAll(); + $models2=Post::model()->findAll(array('scopes'=>array('post23','post3'))); + + foreach(array($models1,$models2) as $models) + { + $this->assertEquals(1,count($models)); + $this->assertEquals(3,$models[0]->id); + } + + $models1=Post::model()->post23()->findAll('id=3'); + $models2=Post::model()->post23()->findAll(array('condition'=>'id=3','scopes'=>'post23')); + + foreach(array($models1,$models2) as $models) + { + $this->assertEquals(1,count($models)); + $this->assertEquals(3,$models[0]->id); + } + + $models1=Post::model()->recent()->with('author')->findAll(); + $models2=Post::model()->with('author')->findAll(array('scopes'=>'recent')); + $models3=Post::model()->with('author')->findAll(array('scopes'=>array('recent'))); + $models4=Post::model()->with('author')->findAll(array('scopes'=>array(array('recent'=>array())))); + + foreach(array($models1,$models2,$models3,$models4) as $models) + { + $this->assertEquals(5,count($models)); + $this->assertEquals(5,$models[0]->id); + $this->assertEquals(4,$models[1]->id); + } + + $models1=Post::model()->recent(3)->findAll(); + $models2=Post::model()->findAll(array('scopes'=>array('recent'=>3))); + $models3=Post::model()->findAll(array('scopes'=>array(array('recent'=>3)))); + + foreach(array($models1,$models2,$models3) as $models) + { + $this->assertEquals(3,count($models)); + $this->assertEquals(5,$models[0]->id); + $this->assertEquals(4,$models[1]->id); + } + + //default scope + $models=PostSpecial::model()->findAll(); + $this->assertEquals(2,count($models)); + $this->assertEquals(2,$models[0]->id); + $this->assertEquals(3,$models[1]->id); + + //default scope + scope + $models1=PostSpecial::model()->desc()->findAll(); + $models2=PostSpecial::model()->findAll(array('scopes'=>'desc')); + + foreach(array($models1,$models2) as $models) + { + $this->assertEquals(2,count($models)); + $this->assertEquals(3,$models[0]->id); + $this->assertEquals(2,$models[1]->id); + } + + //behavior scope + $models=Post::model()->findAll(array('scopes'=>'behaviorPost23')); + $this->assertEquals(2,count($models)); + $this->assertEquals(2,$models[0]->id); + $this->assertEquals(3,$models[1]->id); + + //behavior parametrized scope + $models=Post::model()->findAll(array('scopes'=>array('behaviorRecent'=>3))); + $this->assertEquals(3,count($models)); + $this->assertEquals(5,$models[0]->id); + $this->assertEquals(4,$models[1]->id); + } + + public function testScopeWithRelations() + { + $user1=User::model()->with('posts:post23')->findByPk(2); + $user2=User::model()->with(array('posts'=>array('scopes'=>'post23')))->findByPk(2); + $user3=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>'post23')))); + //ensure alais overloading work correctly + $user4=User::model()->with(array('posts:post23A'=>array('alias'=>'alias')))->findByPk(2); + $user5=User::model()->with(array('posts'=>array('scopes'=>'post23A','alias'=>'alias')))->findByPk(2); + $user6=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>'post23A','alias'=>'alias')))); + + foreach(array($user1,$user2,$user3,$user4,$user5,$user6) as $user) + { + $this->assertEquals(2,count($user->posts)); + $this->assertEquals(2,$user->posts[0]->id); + $this->assertEquals(3,$user->posts[1]->id); + } + + $user1=User::model()->with(array('posts'=>array('scopes'=>array('p'=>4))))->findByPk(2); + $user2=User::model()->with(array('posts'=>array('scopes'=>array('p'=>array(4)))))->findByPk(2); + $user3=User::model()->with(array('posts'=>array('scopes'=>array(array('p'=>4)))))->findByPk(2); + $user4=User::model()->with(array('posts'=>array('scopes'=>array(array('p'=>array(4))))))->findByPk(2); + $user5=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>array('p'=>4))))); + $user6=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>array('p'=>array(4)))))); + $user7=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>array(array('p'=>4)))))); + $user8=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>array(array('p'=>array(4))))))); + + foreach(array($user1,$user2,$user3,$user4,$user5,$user6,$user7,$user8) as $user) + { + $this->assertEquals(1,count($user->posts)); + $this->assertEquals(4,$user->posts[0]->id); + } + + $user=UserSpecial::model()->findByPk(2); + $posts=$user->posts; + $this->assertEquals(2,count($posts)); + $this->assertEquals(2,$posts[0]->id); + $this->assertEquals(3,$posts[1]->id); + + $user=UserSpecial::model()->findByPk(2); + $posts=$user->posts(array('params'=>array(':id1'=>4),'order'=>'posts.id DESC')); + $this->assertEquals(2,count($posts)); + $this->assertEquals(4,$posts[0]->id); + $this->assertEquals(3,$posts[1]->id); + + $user=User::model()->with('posts:post23')->findByPk(2); + $posts=$user->posts(array('scopes'=>'post23')); + $this->assertEquals(2,count($posts)); + $this->assertEquals(2,$posts[0]->id); + $this->assertEquals(3,$posts[1]->id); + + //related model behavior scope + $user1=User::model()->with('posts:behaviorPost23')->findByPk(2); + $user2=User::model()->with(array('posts'=>array('scopes'=>'behaviorPost23')))->findByPk(2); + $user3=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>'behaviorPost23')))); + + foreach(array($user1,$user2,$user3) as $user) + { + $this->assertEquals(2,count($user->posts)); + $this->assertEquals(2,$user->posts[0]->id); + $this->assertEquals(3,$user->posts[1]->id); + } + + //related model with behavior parametrized scope + $user1=User::model()->with(array('posts'=>array('scopes'=>array('behaviorP'=>4))))->findByPk(2); + $user2=User::model()->with(array('posts'=>array('scopes'=>array('behaviorP'=>array(4)))))->findByPk(2); + $user3=User::model()->with(array('posts'=>array('scopes'=>array(array('behaviorP'=>4)))))->findByPk(2); + $user4=User::model()->with(array('posts'=>array('scopes'=>array(array('behaviorP'=>array(4))))))->findByPk(2); + $user5=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>array('behaviorP'=>4))))); + $user6=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>array('behaviorP'=>array(4)))))); + $user7=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>array(array('behaviorP'=>4)))))); + $user8=User::model()->findByPk(2,array('with'=>array('posts'=>array('scopes'=>array(array('behaviorP'=>array(4))))))); + + foreach(array($user1,$user2,$user3,$user4,$user5,$user6,$user7,$user8) as $user) + { + $this->assertEquals(1,count($user->posts)); + $this->assertEquals(4,$user->posts[0]->id); + } + + //related model with 'scopes' as relation option + $user=User::model()->with('postsOrderDescFormat1')->findByPk(2); + $this->assertEquals(3,count($user->postsOrderDescFormat1)); + $this->assertEquals(array(4,3,2),array( + $user->postsOrderDescFormat1[0]->id, + $user->postsOrderDescFormat1[1]->id, + $user->postsOrderDescFormat1[2]->id, + )); + $user=User::model()->with('postsOrderDescFormat2')->findByPk(2); + $this->assertEquals(3,count($user->postsOrderDescFormat2)); + $this->assertEquals(array(4,3,2),array( + $user->postsOrderDescFormat2[0]->id, + $user->postsOrderDescFormat2[1]->id, + $user->postsOrderDescFormat2[2]->id, + )); + } + + public function testResetScope() + { + // resetting named scope + $posts=Post::model()->post23()->resetScope()->findAll(); + $this->assertEquals(5,count($posts)); + + // resetting default scope + $posts=PostSpecial::model()->resetScope()->findAll(); + $this->assertEquals(5,count($posts)); + } + + public function testJoinWithoutSelect() + { + // 1:1 test + $groups=Group::model()->findAll(array( + 'with'=>array( + 'description'=>array( + 'select'=>false, + 'joinType'=>'INNER JOIN', + ), + ), + )); + + $result=array(); + foreach($groups as $group) + { + // there should be nothing in relation + $this->assertFalse($group->hasRelated('description')); + $result[]=array($group->id,$group->name); + } + + $this->assertEquals(array( + array(1,'group1'), + array(2,'group2'), + array(3,'group3'), + array(4,'group4'), + ),$result); + + // 1:M test + $users=User::model()->findAll(array( + 'with'=>array( + 'roles'=>array( + 'select'=>false, + 'joinType'=>'INNER JOIN', + ), + ), + )); + + $result=array(); + foreach($users as $user) + { + // there should be nothing in relation + $this->assertFalse($user->hasRelated('roles')); + $result[]=array($user->id,$user->username,$user->email); + } + + $this->assertEquals(array( + array(1,'user1','email1'), + array(2,'user2','email2'), + ),$result); + } + + public function testHasManyThroughEager() + { + // just bridge + $user=User::model()->with('groups')->findByPk(1); + + $result=array(); + foreach($user->groups as $group) + $result[]=array($user->username,$group->name); + + $this->assertEquals(array( + array('user1','group1'), + array('user1','group2'), + ),$result); + + // just bridge, base limited + $users=User::model()->with('groups')->findAll(array('limit'=>1)); + + $result=array(); + foreach($users as $user) + { + foreach($user->groups as $group) + $result[]=array($user->username,$group->name); + } + + $this->assertEquals(array( + array('user1','group1'), + array('user1','group2'), + ),$result); + + // 'through' should not clear existing relations defined via short syntax + $user=User::model()->with('groups.description')->findByPk(1); + + $result=array(); + foreach($user->groups as $group) + $result[]=array($user->username,$group->name,$group->description->name); + + $this->assertEquals(array( + array('user1','group1','room1'), + array('user1','group2','room2'), + ),$result); + + // 'through' should not clear existing with + $user=User::model()->with(array('groups'=>array('with'=>'description')))->findByPk(1); + + $result=array(); + foreach($user->groups as $group) + $result[]=array($user->username,$group->name,$group->description->name); + + $this->assertEquals(array( + array('user1','group1','room1'), + array('user1','group2','room2'), + ),$result); + + // bridge fields handling + $user=User::model()->with('roles','groups')->findByPk(1); + + $result=array(); + foreach($user->groups as $group) + $result[]=array($user->username,$group->name); + + $this->assertEquals(array( + array('user1','group1'), + array('user1','group2'), + ),$result); + + $result=array(); + foreach($user->roles as $role) + $result[]=array($user->username,$role->name); + + $this->assertEquals(array( + array('user1','dev'), + array('user1','user'), + ),$result); + + // bridge fields handling, another relations order + $user=User::model()->with('groups','roles')->findByPk(1); + + $result=array(); + foreach($user->groups as $group) + $result[]=array($user->username,$group->name); + + $this->assertEquals(array( + array('user1','group1'), + array('user1','group2'), + ),$result); + + $result=array(); + foreach($user->roles as $role) + $result[]=array($user->username,$role->name); + + $this->assertEquals(array( + array('user1','dev'), + array('user1','user'), + ),$result); + + // bridge fields handling, base limited + $users=User::model()->with('roles','groups')->findAll(array('limit'=>1)); + + $result=array(); + foreach($users as $user) + { + foreach($user->groups as $group) + $result[]=array($user->username,$group->name); + } + + $this->assertEquals(array( + array('user1','group1'), + array('user1','group2'), + ),$result); + + $result=array(); + foreach($users as $user) + { + foreach($user->roles as $role) + $result[]=array($user->username,$role->name); + } + + $this->assertEquals(array( + array('user1','dev'), + array('user1','user'), + ),$result); + + // nested through + $group=Group::model()->with('comments')->findByPk(1); + + $result=array(); + foreach($group->comments as $comment) + $result[]=array($group->name,$comment->content); + + $this->assertEquals(array( + array('group1','comment 1'), + array('group1','comment 2'), + array('group1','comment 3'), + array('group1','comment 4'), + array('group1','comment 5'), + array('group1','comment 6'), + array('group1','comment 7'), + array('group1','comment 8'), + array('group1','comment 9'), + ),$result); + + // nested through, base limited + $groups=Group::model()->with('comments')->findAll(array('limit'=>1)); + + $result=array(); + foreach($groups as $group) + { + foreach($group->comments as $comment) + $result[]=array($group->name,$comment->content); + } + + $this->assertEquals(array( + array('group1','comment 1'), + array('group1','comment 2'), + array('group1','comment 3'), + array('group1','comment 4'), + array('group1','comment 5'), + array('group1','comment 6'), + array('group1','comment 7'), + array('group1','comment 8'), + array('group1','comment 9'), + ),$result); + + // self through + $teachers=User::model()->with('students')->findAll(); + + $result=array(); + foreach($teachers as $teacher) + { + foreach($teacher->students as $student) + $result[]=array($teacher->username,$student->username); + } + + $this->assertEquals(array( + array('user1','user3'), + array('user2','user4'), + ),$result); + + // self through, bridge fields handling for right part + $teachers=User::model()->with('mentorships','students')->findAll(); + + $result=array(); + foreach($teachers as $teacher) + { + foreach($teacher->students as $student) + $result[$student->primaryKey]=array('teacher'=>$teacher->username,'student'=>$student->username); + + foreach($teacher->mentorships as $mentorship) + $result[$mentorship->student_id]['progress']=$mentorship->progress; + } + + $this->assertEquals(array( + 3=>array('teacher'=>'user1','student'=>'user3','progress'=>'good'), + 4=>array('teacher'=>'user2','student'=>'user4','progress'=>'average'), + ),$result); + + // self through, base limited + $teachers=User::model()->with('students')->findAll(array('limit'=>1)); + + $result=array(); + foreach($teachers as $teacher) + { + foreach($teacher->students as $student) + $result[]=array($teacher->username,$student->username); + } + + $this->assertEquals(array( + array('user1','user3'), + ),$result); + } + + public function testHasManyThroughLazy() + { + $user=User::model()->findByPk(1); + + $result=array(); + foreach($user->groups as $group) + $result[]=array($user->username,$group->name); + + $this->assertEquals(array( + array('user1','group1'), + array('user1','group2'), + ),$result); + + + $user=User::model()->findByPk(1); + + $result=array(); + foreach($user->groups(array('with'=>'description')) as $group) + $result[]=array($user->username,$group->name,$group->description->name); + + $this->assertEquals(array( + array('user1','group1','room1'), + array('user1','group2','room2'), + ),$result); + + // nested through + $group=Group::model()->findByPk(1); + + $result=array(); + foreach($group->comments as $comment) + $result[]=array($group->name,$comment->content); + + $this->assertEquals(array( + array('group1','comment 1'), + array('group1','comment 2'), + array('group1','comment 3'), + array('group1','comment 4'), + array('group1','comment 5'), + array('group1','comment 6'), + array('group1','comment 7'), + array('group1','comment 8'), + array('group1','comment 9'), + ),$result); + + // self through + $teacher=User::model()->findByPk(1); + + $result=array(); + foreach($teacher->students as $student) + $result[]=array($teacher->username,$student->username); + + $this->assertEquals(array( + array('user1','user3'), + ),$result); + } + + /** + * @see issue2274 + */ + function testMergingWith() + { + User::model()->nonEmptyPosts()->findAll(array( + 'with'=>array( + 'posts'=>array( + 'joinType'=>'INNER JOIN', + ), + ) + )); + } + + /** + * @see github issue 206 + * Unable to pass CDbCriteria to relation while array works fine. + */ + public function testIssue206() + { + $user = User::model()->findByPk(2); + $result1 = $user->posts(array('condition' => 'id IN (2,3)')); + + $criteria = new CDbCriteria(); + $criteria->addInCondition('id', array(2,3)); + $user = User::model()->findByPk(2); + $result2 = $user->posts($criteria); + + $this->assertEquals($result1, $result2); + } + + /** + * https://github.com/yiisoft/yii/issues/1070 + */ + public function testIssue1070() + { + $dataProvider=new CActiveDataProvider('UserWithDefaultScope'); + + foreach($dataProvider->getData() as $item) + { + try + { + $item->links[0]->from_user; + $result=true; + } + catch ( CDbException $e ) + { + $result=false; + } + + $this->assertTrue($result); + } + } + + /** + * https://github.com/yiisoft/yii/issues/507 + */ + public function testIssue507() + { + $this->assertEquals(2, count(UserWithDefaultScope::model()->findAll())); + + } + + /** + * @see https://github.com/yiisoft/yii/issues/135 + */ + public function testCountWithHaving() + { + $criteriaWithHaving = new CDbCriteria(); + $criteriaWithHaving->group = 'id'; + $criteriaWithHaving->having = 'id = 1'; + $count = Post::model()->count($criteriaWithHaving); + + $this->assertEquals(1, $count, 'Having condition has not been applied on count!'); + } + + /** + * @see https://github.com/yiisoft/yii/issues/135 + * @see https://github.com/yiisoft/yii/issues/2201 + */ + public function testCountWithHavingRelational() + { + $criteriaWithHaving = new CDbCriteria(); + $criteriaWithHaving->select = 't.id AS test_field'; + $criteriaWithHaving->with = array('author'); + $criteriaWithHaving->group = 't.id'; + $criteriaWithHaving->having = 'test_field = :test_field'; + $criteriaWithHaving->params['test_field'] = 1; + $count = Post::model()->count($criteriaWithHaving); + + $this->assertEquals(1, $count, 'Having condition has not been applied on count with relation!'); + } + + /** + * @depends testFind + * + * @see https://github.com/yiisoft/yii/issues/2216 + */ + public function testFindBySinglePkByArrayWithMixedKeys() + { + $posts=Post::model()->findAllByPk(array('some'=>3)); + $this->assertEquals(1,count($posts)); + $this->assertEquals(3,$posts[0]->id); + + $posts=Post::model()->findAllByPk(array('some'=>3, 'another'=>2)); + $this->assertEquals(2,count($posts)); + $this->assertEquals(2,$posts[0]->id); + $this->assertEquals(3,$posts[1]->id); + } + + /** + * @depends testFind + * + * @see https://github.com/yiisoft/yii/issues/101 + */ + public function testHasManyThroughHasManyWithCustomSelect() + { + $model=User::model()->with('studentsCustomSelect')->findByPk(1); + $this->assertTrue(is_object($model),'Unable to get master records!'); + $this->assertTrue(count($model->students)>0,'Empty slave records!'); + } + + /** + * @depends testFind + * + * @see https://github.com/yiisoft/yii/issues/139 + */ + public function testLazyLoadThroughRelationWithCondition() + { + $masterModel=Group::model()->findByPk(1); + $this->assertTrue(count($masterModel->users)>0,'Test environment is missing!'); + $this->assertEquals(0,count($masterModel->usersWhichEmptyByCondition),'Unable to apply condition from through relation!'); + } + + /** + * @depends testFind + * + * @see https://github.com/yiisoft/yii/issues/662 + */ + public function testThroughBelongsToLazy() + { + $comments=Comment::model()->findAll(); + foreach($comments as $comment) + { + $this->assertFalse(empty($comment->postAuthor)); + // equal relation definition with BELONGS_TO: https://github.com/yiisoft/yii/pull/2530 + $this->assertFalse(empty($comment->postAuthorBelongsTo)); + $this->assertTrue($comment->postAuthor->equals($comment->postAuthorBelongsTo)); + } + } + + public function testThroughBelongsEager() + { + $comments=Comment::model()->with('postAuthorBelongsTo')->findAll(); + foreach($comments as $comment) + { + $this->assertFalse(empty($comment->postAuthor)); + // equal relation definition with BELONGS_TO: https://github.com/yiisoft/yii/pull/2530 + $this->assertFalse(empty($comment->postAuthorBelongsTo)); + $this->assertTrue($comment->postAuthor->equals($comment->postAuthorBelongsTo)); + } + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/models.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/models.php new file mode 100644 index 0000000..40723fd --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/models.php @@ -0,0 +1,985 @@ +'/^[\d\w_]+$/'), + array('email', 'email'), + array('username', 'length', 'min'=>3, 'max'=>32), + array('password', 'length', 'min'=>6, 'max'=>32), + ); + } + + public function relations() + { + return array( + 'roles'=>array(self::HAS_MANY,'Role','user_id'), + 'groups'=>array(self::HAS_MANY,'Group',array('group_id'=>'id'),'through'=>'roles'), + 'mentorships'=>array(self::HAS_MANY,'Mentorship','teacher_id','joinType'=>'INNER JOIN'), + 'students'=>array(self::HAS_MANY,'User',array('student_id'=>'id'),'through'=>'mentorships','joinType'=>'INNER JOIN'), + 'posts'=>array(self::HAS_MANY,'Post','author_id'), + 'postsOrderDescFormat1'=>array(self::HAS_MANY,'Post','author_id','scopes'=>'orderDesc'), + 'postsOrderDescFormat2'=>array(self::HAS_MANY,'Post','author_id','scopes'=>array('orderDesc')), + 'postCount'=>array(self::STAT,'Post','author_id'), + /* For {@link CActiveRecordTest::testHasManyThroughHasManyWithCustomSelect()}: */ + 'mentorshipsCustomSelect'=>array(self::HAS_MANY,'Mentorship','teacher_id','select' => array('teacher_id', 'student_id')), + 'studentsCustomSelect'=>array(self::HAS_MANY,'User',array('student_id'=>'id'),'through'=>'mentorshipsCustomSelect','select' => array('id', 'username')), + ); + } + + public function tableName() + { + return 'users'; + } + + public function scopes() + { + return array( + 'nonEmptyPosts'=>array( + 'with'=>array( + 'posts'=>array( + 'condition'=>'posts.id is not NULL', + ), + ), + ), + ); + } +} + +/** + * @property integer $teacher_id + * @property integer $student_id + * @property string $progress + */ +class Mentorship extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'mentorships'; + } +} + +/** + * @property integer $id + * @property string $name + */ +class Group extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'roles'=>array(self::HAS_MANY,'Role','group_id'), + 'users'=>array(self::HAS_MANY,'User',array('user_id'=>'id'),'through'=>'roles'), + 'comments'=>array(self::HAS_MANY,'Comment',array('id'=>'author_id'),'through'=>'users'), + 'description'=>array(self::HAS_ONE,'GroupDescription','group_id'), + /* Support for {@link CActiveRecordTest::testLazyLoadThroughRelationWithCondition()}: */ + 'rolesWhichEmptyByCondition'=>array(self::HAS_MANY,'Role','group_id','condition'=>'2=:compareValue','params'=>array(':compareValue'=>1)), + 'usersWhichEmptyByCondition'=>array(self::HAS_MANY,'User',array('user_id'=>'id'),'through'=>'rolesWhichEmptyByCondition'), + ); + } + + public function tableName() + { + return 'groups'; + } +} + +/** + * @property integer $group_id + * @property string $name + */ +class GroupDescription extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'groups_descriptions'; + } +} + +/** + * @property integer $user_id + * @property integer $group_id + * @property string $name + */ +class Role extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'roles'; + } +} + +/** + * @property integer $id + * @property string $title + * @property float $create_time + * @property integer $author_id + * @property string $content + */ +class Post extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'author'=>array(self::BELONGS_TO,'User','author_id'), + 'firstComment'=>array(self::HAS_ONE,'Comment','post_id','order'=>'firstComment.content'), + 'comments'=>array(self::HAS_MANY,'Comment','post_id','order'=>'comments.content DESC'), + 'commentCount'=>array(self::STAT,'Comment','post_id'), + 'categories'=>array(self::MANY_MANY,'Category','post_category(post_id,category_id)','order'=>'categories.id DESC'), + ); + } + + public function tableName() + { + return 'posts'; + } + + public function behaviors() + { + return array( + 'PostScopesBehavior', + ); + } + + public function scopes() + { + return array( + 'post23'=>array('condition'=>'posts.id=2 OR posts.id=3', 'alias'=>'posts', 'order'=>'posts.id'), + 'post23A'=>array('condition'=>"$this->tableAlias.id=2 OR $this->tableAlias.id=3",'order'=>"$this->tableAlias.id"), + 'post3'=>array('condition'=>'id=3'), + 'postX'=>array('condition'=>'id=:id1 OR id=:id2', 'params'=>array(':id1'=>2, ':id2'=>3)), + 'orderDesc'=>array('order'=>'posts.id DESC','alias'=>'posts'), + ); + } + + public function rules() + { + return array( + array('title', 'required'), + ); + } + + public function recent($limit=5) + { + $this->getDbCriteria()->mergeWith(array( + 'order'=>'create_time DESC', + 'limit'=>$limit, + )); + return $this; + } + + //used for relation model scopes test + public function p($id) + { + $this->getDbCriteria()->mergeWith(array( + 'condition'=>'posts.id=?', + 'params'=>array($id), + )); + return $this; + } +} + +class PostScopesBehavior extends CActiveRecordBehavior +{ + public function behaviorPost23() + { + $this->getOwner()->getDbCriteria()->mergeWith(array( + 'condition'=>'posts.id=2 OR posts.id=3', + 'alias'=>'posts', + 'order'=>'posts.id', + )); + + return $this; + } + + public function behaviorRecent($limit) + { + $this->getOwner()->getDbCriteria()->mergeWith(array( + 'order'=>'create_time DESC', + 'limit'=>$limit, + )); + + return $this; + } + + //used for relation model scopes test + public function behaviorP($id) + { + $this->getOwner()->getDbCriteria()->mergeWith(array( + 'condition'=>'posts.id=?', + 'params'=>array($id), + )); + + return $this; + } +} + +/** + * @property integer $id + * @property string $title + * @property float $create_time + * @property integer $author_id + * @property string $content + */ +class PostSpecial extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'posts'; + } + + public function defaultScope() + { + return array( + 'condition'=>'posts.id=:id1 OR posts.id=:id2', + 'params'=>array(':id1'=>2, ':id2'=>3), + 'alias'=>'posts', + ); + } + + public function scopes() + { + return array( + 'desc'=>array('order'=>'id DESC'), + ); + } +} + +/** + * @property integer $id + * @property string $username + * @property string $password + * @property string $email + */ +class UserSpecial extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'posts'=>array(self::HAS_MANY,'PostSpecial','author_id'), + ); + } + + public function tableName() + { + return 'users'; + } +} + +/** + * @property integer $id + * @property string $title + * @property float $create_time + * @property integer $author_id + * @property string $content + */ +class PostExt extends CActiveRecord +{ + public $title='default title'; + public $id; + + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'posts'; + } + + public function relations() + { + return array( + 'comments'=>array(self::HAS_MANY,'Comment','post_id','order'=>'comments.content DESC','with'=>array('post'=>array('alias'=>'post'), 'author')), + ); + } +} + +/** + * @property integer $id + * @property string $content + * @property integer $post_id + * @property integer $author_id + */ +class Comment extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'post'=>array(self::BELONGS_TO,'Post','post_id'), + 'author'=>array(self::BELONGS_TO,'User','author_id'), + 'postAuthor'=>array(self::HAS_ONE,'User',array('author_id'=>'id'),'through'=>'post'), + 'postAuthorBelongsTo'=>array(self::BELONGS_TO,'User',array('author_id'=>'id'),'through'=>'post'), + ); + } + + public function tableName() + { + return 'comments'; + } +} + +/** + * @property integer $id + * @property string $name + * @property integer $parent_id + */ +class Category extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'categories'; + } + + public function relations() + { + return array( + 'posts'=>array(self::MANY_MANY, 'Post', 'post_category(post_id,category_id)'), + 'parent'=>array(self::BELONGS_TO,'Category','parent_id'), + 'children'=>array(self::HAS_MANY,'Category','parent_id'), + 'nodes'=>array(self::HAS_MANY,'Category','parent_id','with'=>array('parent','children')), + 'postCount'=>array(self::STAT, 'Post', 'post_category(post_id,category_id)'), + ); + } +} + +/** + * @property integer $key1 + * @property integer $key2 + * @property string $name + */ +class Order extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'items'=>array(self::HAS_MANY,'Item','col1, col2'), + 'itemCount'=>array(self::STAT,'Item','col1, col2'), + ); + } + + public function tableName() + { + return 'orders'; + } +} + +/** + * @property integer $id + * @property string $name + * @property integer $col1 + * @property integer $col2 + */ +class Item extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'order'=>array(self::BELONGS_TO,'Order','col1, col2','alias'=>'_order'), + ); + } + + public function tableName() + { + return 'items'; + } +} + +/** + * @property integer $int_col + * @property integer $int_col2 + * @property string $char_col + * @property string $char_col2 + * @property string $char_col3 + * @property string $char_col4 + * @property string $char_col5 + * @property float $float_col + * @property float $float_col2 + * @property string $blob_col + * @property float $numeric_col + * @property float $time + * @property integer $bool_col + * @property integer $bool_col2 + * @property integer $null_col + */ +class ComplexType extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'types'; + } +} + +/** + * @property integer $id + * @property string $class + * @property integer $parentID + * @property integer $ownerID + * @property string $title + */ +class Content extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'Content'; + } + + public function relations() + { + return array( + 'parent'=>array(self::BELONGS_TO,'Content','parentID'), + 'children'=>array(self::HAS_MANY,'Content','parentID'), + 'owner'=>array(self::BELONGS_TO,'User','ownerID'), + ); + } +} + +/** + * @property integer $id + * @property integer $authorID + * @property string $body + */ +class Article extends Content +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'Article'; + } + + public function relations() + { + return array( + 'author'=>array(self::BELONGS_TO,'User','authorID'), + 'comments'=>array(self::HAS_MANY,'ArticleComment','parentID'), + ); + } +} + +/** + * @property integer $id + * @property integer $authorID + * @property string $body + */ +class ArticleComment extends Content +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'Comment'; + } + + public function relations() + { + return array( + 'author'=>array(self::BELONGS_TO,'User','authorID'), + 'article'=>array(self::BELONGS_TO,'Article','parentID'), + ); + } +} + +/** + * @property integer $id + * @property string $username + * @property string $password + * @property string $email + */ +class UserNoFk extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'posts'=>array(self::HAS_MANY,'PostNoFk','author_id'), + ); + } + + public function tableName() + { + return 'users'; + } +} + +/** + * @property integer $id + * @property string $title + * @property float $create_time + * @property integer $author_id + * @property string $content + */ +class PostNoFk extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'author'=>array(self::BELONGS_TO,'UserNoFk','author_id'), + ); + } + + public function tableName() + { + return 'posts_nofk'; + } +} + +/** + * @property integer $id + * @property string $username + * @property string $password + * @property string $email + */ +class UserNoTogether extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'posts'=>array(self::HAS_MANY,'PostNoTogether','author_id','together'=>false,'joinType'=>'INNER JOIN'), + ); + } + + public function tableName() + { + return 'users'; + } +} + +/** + * @property integer $id + * @property string $title + * @property float $create_time + * @property integer $author_id + * @property string $content + */ +class PostNoTogether extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'comments'=>array(self::HAS_MANY,'Comment','post_id','together'=>false,'joinType'=>'INNER JOIN'), + ); + } + + public function tableName() + { + return 'posts'; + } +} + +/** + * @property integer $id + * @property string $username + * @property string $password + * @property string $email + */ +class UserWithWrappers extends CActiveRecord +{ + private static $_counters=array(); + + private static $_beforeFindCriteria; + + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'posts'=>array(self::HAS_MANY,'PostWithWrappers','author_id'), + 'postsWithScope'=>array(self::HAS_MANY,'PostWithWrappers','author_id','scopes'=>array('replaceContent')), + 'postCount'=>array(self::STAT,'PostWithWrappers','author_id'), + 'comments'=>array(self::HAS_MANY,'CommentWithWrappers',array('id'=>'post_id'),'through'=>'posts') + ); + } + + public function tableName() + { + return 'users'; + } + + protected function beforeFind() + { + parent::beforeFind(); + $this->incrementCounter(__FUNCTION__); + + if (self::$_beforeFindCriteria!==null) { + $this->getDbCriteria()->mergeWith(self::$_beforeFindCriteria); + } + } + + protected function afterFind() + { + parent::afterFind(); + $this->incrementCounter(__FUNCTION__); + } + + protected function incrementCounter($wrapper) + { + if(isset(self::$_counters[$wrapper])) + self::$_counters[$wrapper]++; + else + self::$_counters[$wrapper]=1; + } + + public static function getCounter($wrapper) + { + if(isset(self::$_counters[$wrapper])) + { + $result=self::$_counters[$wrapper]; + } + else + $result=0; + + self::clearCounters(); + + return $result; + } + + public static function clearCounters() + { + self::$_counters=array(); + } + + public static function setBeforeFindCriteria($criteria) + { + self::$_beforeFindCriteria=(empty($criteria) ? null : $criteria); + } +} + +/** + * @property integer $id + * @property string $title + * @property float $create_time + * @property integer $author_id + * @property string $content + */ +class PostWithWrappers extends CActiveRecord +{ + private static $_counters=array(); + + private static $_beforeFindCriteria; + + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'author'=>array(self::BELONGS_TO,'UserWithWrappers','author_id'), + 'comments'=>array(self::HAS_MANY,'CommentWithWrappers','post_id','order'=>'comments.content DESC'), + 'commentCount'=>array(self::STAT,'CommentWithWrappers','post_id'), + ); + } + + public function tableName() + { + return 'posts'; + } + + public function rules() + { + return array( + array('title', 'required'), + ); + } + + protected function beforeFind() + { + parent::beforeFind(); + $this->incrementCounter(__FUNCTION__); + + if (self::$_beforeFindCriteria!==null) { + $this->getDbCriteria()->mergeWith(self::$_beforeFindCriteria); + } + } + + protected function afterFind() + { + parent::afterFind(); + $this->incrementCounter(__FUNCTION__); + } + + public function scopes() + { + return array( + 'rename'=>array( + 'select'=>"'renamed post' AS title", + ), + 'replaceContent' => array( + 'select'=>"'replaced content' AS content", + ), + ); + } + + protected function incrementCounter($wrapper) + { + if(isset(self::$_counters[$wrapper])) + self::$_counters[$wrapper]++; + else + self::$_counters[$wrapper]=1; + } + + public static function getCounter($wrapper) + { + if(isset(self::$_counters[$wrapper])) + { + $result=self::$_counters[$wrapper]; + } + else + $result=0; + + self::clearCounters(); + + return $result; + } + + public static function clearCounters() + { + self::$_counters=array(); + } + + public static function setBeforeFindCriteria($criteria) + { + self::$_beforeFindCriteria=(empty($criteria) ? null : $criteria); + } +} + +/** + * @property integer $id + * @property string $content + * @property integer $post_id + * @property integer $author_id + */ +class CommentWithWrappers extends CActiveRecord +{ + private static $_counters=array(); + + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'post'=>array(self::BELONGS_TO,'PostWithWrappers','post_id'), + 'author'=>array(self::BELONGS_TO,'UserWithWrappers','author_id'), + ); + } + + public function tableName() + { + return 'comments'; + } + + protected function beforeFind() + { + parent::beforeFind(); + $this->incrementCounter(__FUNCTION__); + } + + protected function afterFind() + { + parent::afterFind(); + $this->incrementCounter(__FUNCTION__); + } + + protected function incrementCounter($wrapper) + { + if(isset(self::$_counters[$wrapper])) + self::$_counters[$wrapper]++; + else + self::$_counters[$wrapper]=1; + } + + public static function getCounter($wrapper) + { + if(isset(self::$_counters[$wrapper])) + { + $result=self::$_counters[$wrapper]; + } + else + $result=0; + + self::clearCounters(); + + return $result; + } + + public static function clearCounters() + { + self::$_counters=array(); + } +} + +/** + * @property integer $id + * @property integer $deleted + * @property string $name + */ +class UserWithDefaultScope extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'UserWithDefaultScope'; + } + + public function defaultScope() + { + $alias=$this->getTableAlias(false,false); + + return array( + 'condition'=>"{$alias}.deleted IS NULL", + 'order'=>"{$alias}.name ASC", + ); + } + + public function relations() + { + return array( + 'links'=>array(self::HAS_MANY,'UserWithDefaultScopeLink','from_id'), + ); + } +} + +/** + * @property integer $id + * @property integer $from_id + * @property integer $to_id + */ +class UserWithDefaultScopeLink extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'UserWithDefaultScopeLink'; + } + + public function relations() + { + return array( + 'from_user'=>array(self::BELONGS_TO,'UserWithDefaultScope','from_id'), + 'to_user'=>array(self::BELONGS_TO,'UserWithDefaultScope','to_id'), + ); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/models2.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/models2.php new file mode 100644 index 0000000..b52b933 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/models2.php @@ -0,0 +1,263 @@ +'/^[\d\w_]+$/'), + array('email', 'email'), + array('username', 'length', 'min'=>3, 'max'=>32), + array('password', 'length', 'min'=>6, 'max'=>32), + ); + } + + public function relations() + { + return array( + 'posts'=>array(self::HAS_MANY,'Post2','author_id'), + 'friends'=>array(self::MANY_MANY,'User2','test.user_friends(id,friend)'), + + // CActiveRecord2Test::testIssue2122() + 'commentsWithParam'=>array(self::HAS_MANY,'Comment2','author_id','on'=>'"commentsWithParam"."post_id">:postId', + 'params'=>array(':postId'=>1)), + 'postsWithParam'=>array(self::HAS_MANY,'Post2',array('post_id'=>'id'),'through'=>'commentsWithParam'), + ); + } + + public function tableName() + { + return 'test.users'; + } +} + +/** + * @property integer $id + * @property string $title + * @property string $create_time + * @property integer $author_id + * @property string $content + */ +class Post2 extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'author'=>array(self::BELONGS_TO,'User2','author_id'), + 'firstComment'=>array(self::HAS_ONE,'Comment2','post_id','order'=>'"firstComment".content'), + 'comments'=>array(self::HAS_MANY,'Comment2','post_id','order'=>'comments.content DESC'), + 'categories'=>array(self::MANY_MANY,'Category2','test.post_category(post_id,category_id)','order'=>'categories.id DESC'), + ); + } + + public function rules() + { + return array( + array('title', 'required'), + ); + } + + public function tableName() + { + return 'test.posts'; + } +} + +/** + * @property integer $id + * @property string $title + * @property string $create_time + * @property integer $author_id + * @property string $content + */ +class NullablePost2 extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'test.nullable_posts'; + } +} + +/** + * @property integer $id + * @property string $title + * @property string $create_time + * @property integer $author_id + * @property string $content + */ +class PostExt2 extends CActiveRecord +{ + public $title='default title'; + public $id; + + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'test.posts'; + } + + public function relations() + { + return array( + 'comments'=>array(self::HAS_MANY,'Comment2','post_id','order'=>'comments.content DESC','with'=>array('post'=>array('alias'=>'post'), 'author')), + ); + } +} + +/** + * @property integer $id + * @property string $content + * @property integer $post_id + * @property integer $author_id + */ +class Comment2 extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'post'=>array(self::BELONGS_TO,'Post2','post_id'), + 'author'=>array(self::BELONGS_TO,'User2','author_id'), + ); + } + + public function tableName() + { + return 'test.comments'; + } +} + +/** + * @property integer $id + * @property string $name + * @property integer $parent_id + */ +class Category2 extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'test.categories'; + } + + public function relations() + { + return array( + 'posts'=>array(self::MANY_MANY, 'Post2', 'test.post_category(post_id,category_id)'), + 'parent'=>array(self::BELONGS_TO,'Category2','parent_id'), + 'children'=>array(self::HAS_MANY,'Category2','parent_id'), + 'nodes'=>array(self::HAS_MANY,'Category2','parent_id','with'=>array('parent','children')), + ); + } +} + +/** + * @property integer $key1 + * @property integer $key2 + * @property string $name + */ +class Order2 extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'items'=>array(self::HAS_MANY,'Item2','col1, col2'), + ); + } + + public function tableName() + { + return 'test.orders'; + } +} + +/** + * @property integer $id + * @property string $name + * @property integer $col1 + * @property integer $col2 + */ +class Item2 extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function relations() + { + return array( + 'order'=>array(self::BELONGS_TO,'Order2','col1, col2','alias'=>'_order'), + ); + } + + public function tableName() + { + return 'test.items'; + } +} + +/** + * @property integer $int_col + * @property integer $int_col2 + * @property string $char_col + * @property string $char_col2 + * @property string $char_col3 + * @property float $numeric_col + * @property float $real_col + * @property string $blob_col + * @property string $time + * @property integer $bool_col + * @property integer $bool_col2 + */ +class ComplexType2 extends CActiveRecord +{ + public static function model($class=__CLASS__) + { + return parent::model($class); + } + + public function tableName() + { + return 'yii_types'; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/mssql.sql b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/mssql.sql new file mode 100644 index 0000000..0dabe63 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/mssql.sql @@ -0,0 +1,392 @@ +-- ----------------------- +-- Main table creating DDL +-- ----------------------- + +-- create 'categories' table +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[categories]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[categories]( + [id] [int] IDENTITY(1,1) NOT NULL, + [name] [varchar](128) NOT NULL, + [parent_id] [int] NULL, + CONSTRAINT [PK_categories] PRIMARY KEY CLUSTERED( + [id] ASC + ) ON [PRIMARY] +) ON [PRIMARY] +END +GO + +-- create 'orders' table +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[orders]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[orders]( + [key1] [int] NOT NULL, + [key2] [int] NOT NULL, + [name] [varchar](128) NOT NULL, + CONSTRAINT [PK_orders] PRIMARY KEY CLUSTERED( + [key1] ASC, + [key2] ASC + ) ON [PRIMARY] +) ON [PRIMARY] +END +GO + +-- create 'types' table +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[types]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[types]( + [int_col] [int] NOT NULL, + [int_col2] [int] NULL CONSTRAINT [DF_types_int_col2] DEFAULT (1), + [char_col] [char](100) NOT NULL, + [char_col2] [varchar](100) NULL CONSTRAINT [DF_types_char_col2] DEFAULT ('something'), + [char_col3] [text] NULL, + [float_col] [real] NOT NULL, + [float_col2] [float] NULL CONSTRAINT [DF_types_float_col2] DEFAULT (1.23), + [blob_col] [image] NULL, + [numeric_col] [numeric](5, 2) NULL CONSTRAINT [DF_types_numeric_col] DEFAULT (33.22), + [time] [datetime] NULL CONSTRAINT [DF_types_time] DEFAULT ('2002-01-01 00:00:00'), + [bool_col] [bit] NOT NULL, + [bool_col2] [bit] NOT NULL CONSTRAINT [DF_types_bool_col2] DEFAULT (1) +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +END +GO + +-- create 'users' table +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[users]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[users]( + [id] [int] IDENTITY(1,1) NOT NULL, + [username] [varchar](128) NOT NULL, + [password] [varchar](128) NOT NULL, + [email] [varchar](128) NOT NULL, + CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED( + [id] ASC + ) ON [PRIMARY] +) ON [PRIMARY] +END +GO + +-- create 'post_category' table (junction between 'categories' and 'posts') +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[post_category]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[post_category]( + [category_id] [int] NOT NULL, + [post_id] [int] NOT NULL, + CONSTRAINT [PK_post_category] PRIMARY KEY CLUSTERED( + [category_id] ASC, + [post_id] ASC + ) ON [PRIMARY] +) ON [PRIMARY] +END +GO + +-- create 'items' table +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[items]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[items]( + [id] [int] IDENTITY(1,1) NOT NULL, + [name] [varchar](128) NULL, + [col1] [int] NOT NULL, + [col2] [int] NOT NULL, + CONSTRAINT [PK_items] PRIMARY KEY CLUSTERED( + [id] ASC + ) ON [PRIMARY] +) ON [PRIMARY] +END +GO + +-- create 'comments' table +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[comments]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[comments]( + [id] [int] IDENTITY(1,1) NOT NULL, + [content] [text] NOT NULL, + [post_id] [int] NOT NULL, + [author_id] [int] NOT NULL, + CONSTRAINT [PK_comments] PRIMARY KEY CLUSTERED( + [id] ASC + ) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +END +GO + +-- create 'posts' table +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[posts]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[posts]( + [id] [int] IDENTITY(1,1) NOT NULL, + [title] [varchar](128) NOT NULL, + [create_time] [datetime] NOT NULL, + [author_id] [int] NOT NULL, + [content] [text] NULL, + CONSTRAINT [PK_posts] PRIMARY KEY CLUSTERED( + [id] ASC + ) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +END +GO + +-- create 'profiles' table +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[profiles]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) +BEGIN +CREATE TABLE [dbo].[profiles]( + [id] [int] IDENTITY(1,1) NOT NULL, + [first_name] [varchar](128) NOT NULL, + [last_name] [varchar](128) NOT NULL, + [user_id] [int] NOT NULL, + CONSTRAINT [PK_profiles] PRIMARY KEY CLUSTERED( + [id] ASC + ) ON [PRIMARY] +) ON [PRIMARY] +END +GO + +-- ---------------------------- +-- Foreign keys and constraints +-- ---------------------------- + +-- 'categories' table foreign keys +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_categories_categories]') AND type = 'F') +ALTER TABLE [dbo].[categories] WITH CHECK ADD CONSTRAINT [FK_categories_categories] FOREIGN KEY([parent_id]) +REFERENCES [dbo].[categories] ([id]) +GO + +-- 'post_category' table foreign keys +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_post_category_categories]') AND type = 'F') +ALTER TABLE [dbo].[post_category] WITH CHECK ADD CONSTRAINT [FK_post_category_categories] FOREIGN KEY([category_id]) +REFERENCES [dbo].[categories] ([id]) +ON DELETE CASCADE +GO + +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_post_category_posts]') AND type = 'F') +ALTER TABLE [dbo].[post_category] WITH NOCHECK ADD CONSTRAINT [FK_post_category_posts] FOREIGN KEY([post_id]) +REFERENCES [dbo].[posts] ([id]) +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[post_category] CHECK CONSTRAINT [FK_post_category_posts] +GO + +-- 'items' table foreign keys +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_items_orders]') AND type = 'F') +ALTER TABLE [dbo].[items] WITH CHECK ADD CONSTRAINT [FK_items_orders] FOREIGN KEY([col1], [col2]) +REFERENCES [dbo].[orders] ([key1], [key2]) +ON DELETE CASCADE +GO + +-- 'comments' table foreign keys +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_comments_users]') AND type = 'F') +ALTER TABLE [dbo].[comments] WITH NOCHECK ADD CONSTRAINT [FK_comments_users] FOREIGN KEY([author_id]) +REFERENCES [dbo].[users] ([id]) +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[comments] CHECK CONSTRAINT [FK_comments_users] +GO + +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_post_comment]') AND type = 'F') +ALTER TABLE [dbo].[comments] WITH NOCHECK ADD CONSTRAINT [FK_post_comment] FOREIGN KEY([post_id]) +REFERENCES [dbo].[posts] ([id]) +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[comments] CHECK CONSTRAINT [FK_post_comment] +GO + +-- 'posts' table foreign keys +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_posts_users]') AND type = 'F') +ALTER TABLE [dbo].[posts] WITH NOCHECK ADD CONSTRAINT [FK_posts_users] FOREIGN KEY([author_id]) +REFERENCES [dbo].[users] ([id]) +GO +ALTER TABLE [dbo].[posts] CHECK CONSTRAINT [FK_posts_users] +GO + +-- 'profiles' table foreign keys +IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_profile_user]') AND type = 'F') +ALTER TABLE [dbo].[profiles] WITH NOCHECK ADD CONSTRAINT [FK_profile_user] FOREIGN KEY([user_id]) +REFERENCES [dbo].[users] ([id]) +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[profiles] CHECK CONSTRAINT [FK_profile_user] +GO + +-- --------------------------------------------------- +-- Tables' comments (MS_Description extended property) +-- --------------------------------------------------- + +-- 'users' table column comments +EXEC sys.sp_addextendedproperty + @name=N'MS_Description', @value=N'Name of the user', + @level0type=N'SCHEMA', @level0name=N'dbo', + @level1type=N'TABLE', @level1name=N'users', + @level2type=N'COLUMN', @level2name=N'username' +GO +EXEC sys.sp_addextendedproperty + @name=N'MS_Description', @value=N'User''s password', + @level0type=N'SCHEMA', @level0name=N'dbo', + @level1type=N'TABLE', @level1name=N'users', + @level2type=N'COLUMN', @level2name=N'password' +GO +EXEC sys.sp_addextendedproperty + @name=N'MS_Description', @value=N'User''s email', + @level0type=N'SCHEMA', @level0name=N'dbo', + @level1type=N'TABLE', @level1name=N'users', + @level2type=N'COLUMN', @level2name=N'email' +GO + +-- 'profiles' table column comments +EXEC sys.sp_addextendedproperty + @name=N'MS_Description', @value=N'用户å。', + @level0type=N'SCHEMA', @level0name=N'dbo', + @level1type=N'TABLE', @level1name=N'profiles', + @level2type=N'COLUMN', @level2name=N'first_name' +GO +EXEC sys.sp_addextendedproperty + @name=N'MS_Description', @value=N'ТеÑÑ‚ Юникода', + @level0type=N'SCHEMA', @level0name=N'dbo', + @level1type=N'TABLE', @level1name=N'profiles', + @level2type=N'COLUMN', @level2name=N'id' +GO +EXEC sys.sp_addextendedproperty + @name=N'MS_Description', @value=N'User''s identifier', + @level0type=N'SCHEMA', @level0name=N'dbo', + @level1type=N'TABLE', @level1name=N'profiles', + @level2type=N'COLUMN', @level2name=N'user_id' +GO + +-- -------------------------------- +-- Tables' actual testing real data +-- -------------------------------- + +-- 'users' table data +INSERT INTO users (username, password, email) VALUES ('user1','pass1','email1') +GO +INSERT INTO users (username, password, email) VALUES ('user2','pass2','email2') +GO +INSERT INTO users (username, password, email) VALUES ('user3','pass3','email3') +GO + +-- 'profiles' table data +INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 1','last 1',1) +GO +INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 2','last 2',2) +GO + +-- 'posts' table data +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 1','2000-01-01',1,'content 1') +GO +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 2','2000-01-02',2,'content 2') +GO +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 3','2000-01-03',2,'content 3') +GO +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 4','2000-01-04',2,'content 4') +GO +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 5','2000-01-05',3,'content 5') +GO + +-- 'comments' table data +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 1',1, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 2',1, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 3',1, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 4',2, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 5',2, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 6',3, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 7',3, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 8',3, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 9',3, 2) +GO +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 10',5, 3) +GO + +-- 'categories' table data +INSERT INTO categories (name, parent_id) VALUES ('cat 1',NULL) +GO +INSERT INTO categories (name, parent_id) VALUES ('cat 2',NULL) +GO +INSERT INTO categories (name, parent_id) VALUES ('cat 3',NULL) +GO +INSERT INTO categories (name, parent_id) VALUES ('cat 4',1) +GO +INSERT INTO categories (name, parent_id) VALUES ('cat 5',1) +GO +INSERT INTO categories (name, parent_id) VALUES ('cat 6',5) +GO +INSERT INTO categories (name, parent_id) VALUES ('cat 7',5) +GO + +-- 'post_category' table data (junction between 'categories' and 'posts') +INSERT INTO post_category (category_id, post_id) VALUES (1,1) +GO +INSERT INTO post_category (category_id, post_id) VALUES (2,1) +GO +INSERT INTO post_category (category_id, post_id) VALUES (3,1) +GO +INSERT INTO post_category (category_id, post_id) VALUES (4,2) +GO +INSERT INTO post_category (category_id, post_id) VALUES (1,2) +GO +INSERT INTO post_category (category_id, post_id) VALUES (1,3) +GO + +-- 'orders' table data +INSERT INTO orders (key1,key2,name) VALUES (1,2,'order 12') +GO +INSERT INTO orders (key1,key2,name) VALUES (1,3,'order 13') +GO +INSERT INTO orders (key1,key2,name) VALUES (2,1,'order 21') +GO +INSERT INTO orders (key1,key2,name) VALUES (2,2,'order 22') +GO + +-- 'items' table data +INSERT INTO items (name,col1,col2) VALUES ('item 1',1,2) +GO +INSERT INTO items (name,col1,col2) VALUES ('item 2',1,2) +GO +INSERT INTO items (name,col1,col2) VALUES ('item 3',1,3) +GO +INSERT INTO items (name,col1,col2) VALUES ('item 4',2,2) +GO +INSERT INTO items (name,col1,col2) VALUES ('item 5',2,2) +GO diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/mysql.sql b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/mysql.sql new file mode 100644 index 0000000..07f772e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/mysql.sql @@ -0,0 +1,152 @@ +/** + * This is the database schema for testing MySQL support of yii Active Record. + * To test this feature, you need to create a database named 'yii' on 'localhost' + * and create an account 'test/test' which owns this test database. + */ + +CREATE TABLE users +( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(128) NOT NULL COMMENT 'Name of the user', + password VARCHAR(128) NOT NULL COMMENT 'Hashed password', + email VARCHAR(128) NOT NULL +) ENGINE=InnoDB; + +INSERT INTO users (username, password, email) VALUES ('user1','pass1','email1'); +INSERT INTO users (username, password, email) VALUES ('user2','pass2','email2'); +INSERT INTO users (username, password, email) VALUES ('user3','pass3','email3'); + +CREATE TABLE profiles +( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + first_name VARCHAR(128) NOT NULL, + last_name VARCHAR(128) NOT NULL, + user_id INTEGER NOT NULL, + CONSTRAINT FK_profile_user FOREIGN KEY (user_id) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT +) ENGINE=InnoDB; + +INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 1','last 1',1); +INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 2','last 2',2); + +CREATE TABLE posts +( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + title VARCHAR(128) NOT NULL, + create_time TIMESTAMP NOT NULL, + author_id INTEGER NOT NULL, + content TEXT, + CONSTRAINT FK_post_author FOREIGN KEY (author_id) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT +) ENGINE=InnoDB; + +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 1','2000-01-01',1,'content 1'); +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 2','2000-01-02',2,'content 2'); +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 3','2000-01-03',2,'content 3'); +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 4','2000-01-04',2,'content 4'); +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 5','2000-01-05',3,'content 5'); + +CREATE TABLE comments +( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + content TEXT NOT NULL, + post_id INTEGER NOT NULL, + author_id INTEGER NOT NULL, + CONSTRAINT FK_post_comment FOREIGN KEY (post_id) + REFERENCES posts (id) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT FK_user_comment FOREIGN KEY (author_id) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT +) ENGINE=InnoDB; + +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 1',1, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 2',1, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 3',1, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 4',2, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 5',2, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 6',3, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 7',3, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 8',3, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 9',3, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 10',5, 3); + +CREATE TABLE categories +( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(128) NOT NULL, + parent_id INTEGER, + CONSTRAINT FK_category_category FOREIGN KEY (parent_id) + REFERENCES categories (id) ON DELETE CASCADE ON UPDATE RESTRICT +) ENGINE=InnoDB; + +INSERT INTO categories (name, parent_id) VALUES ('cat 1',NULL); +INSERT INTO categories (name, parent_id) VALUES ('cat 2',NULL); +INSERT INTO categories (name, parent_id) VALUES ('cat 3',NULL); +INSERT INTO categories (name, parent_id) VALUES ('cat 4',1); +INSERT INTO categories (name, parent_id) VALUES ('cat 5',1); +INSERT INTO categories (name, parent_id) VALUES ('cat 6',5); +INSERT INTO categories (name, parent_id) VALUES ('cat 7',5); + +CREATE TABLE post_category +( + category_id INTEGER NOT NULL, + post_id INTEGER NOT NULL, + PRIMARY KEY (category_id, post_id), + CONSTRAINT FK_post_category_post FOREIGN KEY (post_id) + REFERENCES posts (id) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT FK_post_category_category FOREIGN KEY (category_id) + REFERENCES categories (id) ON DELETE CASCADE ON UPDATE RESTRICT +) ENGINE=InnoDB; + +INSERT INTO post_category (category_id, post_id) VALUES (1,1); +INSERT INTO post_category (category_id, post_id) VALUES (2,1); +INSERT INTO post_category (category_id, post_id) VALUES (3,1); +INSERT INTO post_category (category_id, post_id) VALUES (4,2); +INSERT INTO post_category (category_id, post_id) VALUES (1,2); +INSERT INTO post_category (category_id, post_id) VALUES (1,3); + +CREATE TABLE orders +( + key1 INTEGER NOT NULL, + key2 INTEGER NOT NULL, + name VARCHAR(128), + PRIMARY KEY (key1, key2) +) ENGINE=InnoDB; + +INSERT INTO orders (key1,key2,name) VALUES (1,2,'order 12'); +INSERT INTO orders (key1,key2,name) VALUES (1,3,'order 13'); +INSERT INTO orders (key1,key2,name) VALUES (2,1,'order 21'); +INSERT INTO orders (key1,key2,name) VALUES (2,2,'order 22'); + +CREATE TABLE items +( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(128), + col1 INTEGER NOT NULL, + col2 INTEGER NOT NULL, + CONSTRAINT FK_order_item FOREIGN KEY (col1,col2) + REFERENCES orders (key1,key2) ON DELETE CASCADE ON UPDATE RESTRICT +) ENGINE=InnoDB; + +INSERT INTO items (name,col1,col2) VALUES ('item 1',1,2); +INSERT INTO items (name,col1,col2) VALUES ('item 2',1,2); +INSERT INTO items (name,col1,col2) VALUES ('item 3',1,3); +INSERT INTO items (name,col1,col2) VALUES ('item 4',2,2); +INSERT INTO items (name,col1,col2) VALUES ('item 5',2,2); + +CREATE TABLE types +( + int_col INT NOT NULL, + int_col2 INTEGER DEFAULT 1, + char_col CHAR(100) NOT NULL, + char_col2 VARCHAR(100) DEFAULT 'something', + char_col3 TEXT, + float_col REAL(4,3) NOT NULL, + float_col2 DOUBLE DEFAULT 1.23, + blob_col BLOB, + numeric_col NUMERIC(5,2) DEFAULT 33.22, + time TIMESTAMP DEFAULT '2002-01-01', + bool_col BOOL NOT NULL, + bool_col2 BOOLEAN DEFAULT 1, + bit_col1 BIT, + bit_col2 BIT(32) DEFAULT b'101010' +) ENGINE=InnoDB; \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/oci.sql b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/oci.sql new file mode 100644 index 0000000..0820127 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/oci.sql @@ -0,0 +1,321 @@ +-- Double EOL symbol (\n\n) used as separator. This means that query string like "{SQL1}\n\n{SQL2}" would +-- cause two queries to the RDBMS: first "{SQL1}" and second "{SQL2}". + +-- Create 'users' table. +CREATE TABLE "users" ( + "id" INTEGER NOT NULL, + "username" VARCHAR2(128 CHAR) NOT NULL, + "password" VARCHAR2(128 CHAR) NOT NULL, + "email" VARCHAR2(128 CHAR) NOT NULL +) LOGGING NOCOMPRESS NOCACHE; + +COMMENT ON COLUMN "users"."id" IS 'User''s entry primary key'; + +COMMENT ON COLUMN "users"."username" IS 'Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ'; + +COMMENT ON COLUMN "users"."password" IS '用户的密ç '; + +COMMENT ON COLUMN "users"."email" IS 'דו×"ל של המשתמש'; + +ALTER TABLE "users" ADD CHECK ("id" IS NOT NULL); + +ALTER TABLE "users" ADD CHECK ("username" IS NOT NULL); + +ALTER TABLE "users" ADD CHECK ("password" IS NOT NULL); + +ALTER TABLE "users" ADD CHECK ("email" IS NOT NULL); + +ALTER TABLE "users" ADD PRIMARY KEY ("id"); + +CREATE SEQUENCE "users_id_sequence" START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "users_id_trigger" +BEFORE INSERT ON "users" +FOR EACH ROW BEGIN + SELECT "users_id_sequence".nextval INTO :new."id" FROM dual; +END; + +-- Create 'profiles' table. +CREATE TABLE "profiles" ( + "id" INTEGER NOT NULL, + "first_name" VARCHAR2(128 CHAR) NOT NULL, + "last_name" VARCHAR2(128 CHAR) NOT NULL, + "user_id" INTEGER NOT NULL +) LOGGING NOCOMPRESS NOCACHE; + +ALTER TABLE "profiles" ADD CHECK ("id" IS NOT NULL); + +ALTER TABLE "profiles" ADD CHECK ("first_name" IS NOT NULL); + +ALTER TABLE "profiles" ADD CHECK ("last_name" IS NOT NULL); + +ALTER TABLE "profiles" ADD CHECK ("user_id" IS NOT NULL); + +ALTER TABLE "profiles" ADD PRIMARY KEY ("id"); + +ALTER TABLE "profiles" ADD FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE; + +CREATE SEQUENCE "profiles_id_sequence" START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "profiles_id_trigger" +BEFORE INSERT ON "profiles" +FOR EACH ROW BEGIN + SELECT "profiles_id_sequence".nextval INTO :new."id" FROM dual; +END; + +-- Create 'posts' table. +CREATE TABLE "posts" ( + "id" INTEGER NOT NULL, + "title" VARCHAR2(128 CHAR) NOT NULL, + "create_time" TIMESTAMP NOT NULL, + "author_id" INTEGER NOT NULL, + "content" CLOB +) LOGGING NOCOMPRESS NOCACHE; + +ALTER TABLE "posts" ADD CHECK ("id" IS NOT NULL); + +ALTER TABLE "posts" ADD CHECK ("title" IS NOT NULL); + +ALTER TABLE "posts" ADD CHECK ("create_time" IS NOT NULL); + +ALTER TABLE "posts" ADD CHECK ("author_id" IS NOT NULL); + +ALTER TABLE "posts" ADD PRIMARY KEY ("id"); + +ALTER TABLE "posts" ADD FOREIGN KEY ("author_id") REFERENCES "users" ("id") ON DELETE CASCADE; + +CREATE SEQUENCE "posts_id_sequence" START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "posts_id_trigger" +BEFORE INSERT ON "posts" +FOR EACH ROW BEGIN + SELECT "posts_id_sequence".nextval INTO :new."id" FROM dual; +END; + +-- Create 'comments' table. +CREATE TABLE "comments" ( + "id" INTEGER NOT NULL, + "content" CLOB, + "post_id" INTEGER NOT NULL, + "author_id" INTEGER NOT NULL +) LOGGING NOCOMPRESS NOCACHE; + +ALTER TABLE "comments" ADD CHECK ("id" IS NOT NULL); + +ALTER TABLE "comments" ADD CHECK ("post_id" IS NOT NULL); + +ALTER TABLE "comments" ADD CHECK ("author_id" IS NOT NULL); + +ALTER TABLE "comments" ADD PRIMARY KEY ("id"); + +ALTER TABLE "comments" ADD FOREIGN KEY ("post_id") REFERENCES "posts" ("id") ON DELETE CASCADE; + +ALTER TABLE "comments" ADD FOREIGN KEY ("author_id") REFERENCES "users" ("id") ON DELETE CASCADE; + +CREATE SEQUENCE "comments_id_sequence" START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "comments_id_trigger" +BEFORE INSERT ON "comments" +FOR EACH ROW BEGIN + SELECT "comments_id_sequence".nextval INTO :new."id" FROM dual; +END; + +-- Create 'categories' table. +CREATE TABLE "categories" ( + "id" INTEGER NOT NULL, + "name" VARCHAR2(128 CHAR) NOT NULL, + "parent_id" INTEGER +) LOGGING NOCOMPRESS NOCACHE; + +ALTER TABLE "categories" ADD CHECK ("id" IS NOT NULL); + +ALTER TABLE "categories" ADD CHECK ("name" IS NOT NULL); + +ALTER TABLE "categories" ADD PRIMARY KEY ("id"); + +ALTER TABLE "categories" ADD FOREIGN KEY ("parent_id") REFERENCES "categories" ("id") ON DELETE CASCADE; + +CREATE SEQUENCE "categories_id_sequence" START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "categories_id_trigger" +BEFORE INSERT ON "categories" +FOR EACH ROW BEGIN + SELECT "categories_id_sequence".nextval INTO :new."id" FROM dual; +END; + +-- Create 'post_category' table. +CREATE TABLE "post_category" ( + "category_id" INTEGER NOT NULL, + "post_id" INTEGER NOT NULL +) LOGGING NOCOMPRESS NOCACHE; + +ALTER TABLE "post_category" ADD CHECK ("category_id" IS NOT NULL); + +ALTER TABLE "post_category" ADD CHECK ("post_id" IS NOT NULL); + +ALTER TABLE "post_category" ADD PRIMARY KEY ("category_id", "post_id"); + +ALTER TABLE "post_category" ADD FOREIGN KEY ("category_id") REFERENCES "posts" ("id") ON DELETE CASCADE; + +ALTER TABLE "post_category" ADD FOREIGN KEY ("post_id") REFERENCES "categories" ("id") ON DELETE CASCADE; + +-- Create 'orders' table. +CREATE TABLE "orders" ( + "key1" INTEGER NOT NULL, + "key2" INTEGER NOT NULL, + "name" VARCHAR2(128 CHAR) NOT NULL +) LOGGING NOCOMPRESS NOCACHE; + +ALTER TABLE "orders" ADD CHECK ("key1" IS NOT NULL); + +ALTER TABLE "orders" ADD CHECK ("key2" IS NOT NULL); + +ALTER TABLE "orders" ADD CHECK ("name" IS NOT NULL); + +ALTER TABLE "orders" ADD PRIMARY KEY ("key1", "key2"); + +-- Create 'items' table. +CREATE TABLE "items" ( + "id" INTEGER NOT NULL, + "name" VARCHAR2(128 CHAR) NOT NULL, + "col1" INTEGER NOT NULL, + "col2" INTEGER NOT NULL +) LOGGING NOCOMPRESS NOCACHE; + +ALTER TABLE "items" ADD CHECK ("id" IS NOT NULL); + +ALTER TABLE "items" ADD CHECK ("name" IS NOT NULL); + +ALTER TABLE "items" ADD CHECK ("col1" IS NOT NULL); + +ALTER TABLE "items" ADD CHECK ("col2" IS NOT NULL); + +ALTER TABLE "items" ADD PRIMARY KEY ("id"); + +ALTER TABLE "items" ADD FOREIGN KEY ("col1", "col2") REFERENCES "orders" ("key1", "key2") ON DELETE CASCADE; + +CREATE SEQUENCE "items_id_sequence" START WITH 1 INCREMENT BY 1 NOMAXVALUE; + +CREATE TRIGGER "items_id_trigger" +BEFORE INSERT ON "items" +FOR EACH ROW BEGIN + SELECT "items_id_sequence".nextval INTO :new."id" FROM dual; +END; + +-- Create 'types' table. +CREATE TABLE "types" ( + "int_col" INT NOT NULL, + "int_col2" INTEGER DEFAULT 1, + "char_col" CHAR(100) NOT NULL, + "char_col2" VARCHAR2(100 CHAR) DEFAULT 'something', + "char_col3" CLOB, + "float_col" NUMBER(4, 3) NOT NULL, + "float_col2" BINARY_DOUBLE DEFAULT 1.23, + "blob_col" BLOB, + "numeric_col" NUMBER(5, 2) DEFAULT 33.22, + "time" TIMESTAMP DEFAULT TO_TIMESTAMP('2010-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS'), + "bool_col" NUMBER(1, 0) NOT NULL, + "bool_col2" NUMBER(1, 0) DEFAULT 1 +) LOGGING NOCOMPRESS NOCACHE; + +ALTER TABLE "types" ADD CHECK ("int_col" IS NOT NULL); + +ALTER TABLE "types" ADD CHECK ("char_col" IS NOT NULL); + +ALTER TABLE "types" ADD CHECK ("float_col" IS NOT NULL); + +ALTER TABLE "types" ADD CHECK ("bool_col" IS NOT NULL); + +-- Data for the 'users' table. +INSERT INTO "users" ("username", "password", "email") VALUES ('user1', 'pass1', 'email1'); + +INSERT INTO "users" ("username", "password", "email") VALUES ('user2', 'pass2', 'email2'); + +INSERT INTO "users" ("username", "password", "email") VALUES ('user3', 'pass3', 'email3'); + +INSERT INTO "users" ("username", "password", "email") VALUES ('пользователь4', '密ç 4', 'דו×"ל4'); + +-- Data for the 'profiles' table. +INSERT INTO "profiles" ("first_name", "last_name", "user_id") VALUES ('first 1', 'last 1', 1); + +INSERT INTO "profiles" ("first_name", "last_name", "user_id") VALUES ('first 2', 'last 2', 2); + +-- Data for the 'posts' table. +INSERT INTO "posts" ("title", "create_time", "author_id", "content") VALUES ('post 1', TIMESTAMP '2000-01-01 00:00:00', 1, 'content 1'); + +INSERT INTO "posts" ("title", "create_time", "author_id", "content") VALUES ('post 2', TIMESTAMP '2000-01-02 00:00:00', 2, 'content 2'); + +INSERT INTO "posts" ("title", "create_time", "author_id", "content") VALUES ('post 3', TIMESTAMP '2000-01-03 00:00:00', 2, 'content 3'); + +INSERT INTO "posts" ("title", "create_time", "author_id", "content") VALUES ('post 4', TIMESTAMP '2000-01-04 00:00:00', 2, 'content 4'); + +INSERT INTO "posts" ("title", "create_time", "author_id", "content") VALUES ('post 5', TIMESTAMP '2000-01-05 00:00:00', 3, 'content 5'); + +-- Data for the 'comments' table. +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 1', 1, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 2', 1, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 3', 1, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 4', 2, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 5', 2, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 6', 3, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 7', 3, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 8', 3, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 9', 3, 2); + +INSERT INTO "comments" ("content", "post_id", "author_id") VALUES ('comment 10', 5, 3); + +-- Data for the 'categories' table. +INSERT INTO "categories" ("name", "parent_id") VALUES ('cat 1', NULL); + +INSERT INTO "categories" ("name", "parent_id") VALUES ('cat 2', NULL); + +INSERT INTO "categories" ("name", "parent_id") VALUES ('cat 3', NULL); + +INSERT INTO "categories" ("name", "parent_id") VALUES ('cat 4', 1); + +INSERT INTO "categories" ("name", "parent_id") VALUES ('cat 5', 1); + +INSERT INTO "categories" ("name", "parent_id") VALUES ('cat 6', 5); + +INSERT INTO "categories" ("name", "parent_id") VALUES ('cat 7', 5); + +-- Data for the 'post_category' table. +INSERT INTO "post_category" ("category_id", "post_id") VALUES (1, 1); + +INSERT INTO "post_category" ("category_id", "post_id") VALUES (2, 1); + +INSERT INTO "post_category" ("category_id", "post_id") VALUES (3, 1); + +INSERT INTO "post_category" ("category_id", "post_id") VALUES (4, 2); + +INSERT INTO "post_category" ("category_id", "post_id") VALUES (1, 2); + +INSERT INTO "post_category" ("category_id", "post_id") VALUES (1, 3); + +-- Data for the 'orders' table. +INSERT INTO "orders" ("key1", "key2", "name") VALUES (1, 2, 'order 12'); + +INSERT INTO "orders" ("key1", "key2", "name") VALUES (1, 3, 'order 13'); + +INSERT INTO "orders" ("key1", "key2", "name") VALUES (2, 1, 'order 21'); + +INSERT INTO "orders" ("key1", "key2", "name") VALUES (2, 2, 'order 22'); + +-- Data for the 'items' table. +INSERT INTO "items" ("name", "col1", "col2") VALUES ('item 1', 1, 2); + +INSERT INTO "items" ("name", "col1", "col2") VALUES ('item 2', 1, 2); + +INSERT INTO "items" ("name", "col1", "col2") VALUES ('item 3', 1, 3); + +INSERT INTO "items" ("name", "col1", "col2") VALUES ('item 4', 2, 2); + +INSERT INTO "items" ("name", "col1", "col2") VALUES ('item 5', 2, 2); diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/postgres.sql b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/postgres.sql new file mode 100644 index 0000000..85f9242 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/postgres.sql @@ -0,0 +1,179 @@ +/** + * This is the database schema for testing PostgreSQL support of yii Active Record. + * To test this feature, you need to create a database named 'yii' on 'localhost' + * and create an account 'test/test' which owns this test database. + */ +CREATE SCHEMA test; + +CREATE TABLE test.users +( + id SERIAL NOT NULL PRIMARY KEY, + username VARCHAR(128) NOT NULL, + password VARCHAR(128) NOT NULL, + email VARCHAR(128) NOT NULL +); + +COMMENT ON COLUMN test.users.username IS 'Name of the user'; +COMMENT ON COLUMN test.users.password IS 'Hashed password'; + +INSERT INTO test.users (username, password, email) VALUES ('user1','pass1','email1'); +INSERT INTO test.users (username, password, email) VALUES ('user2','pass2','email2'); +INSERT INTO test.users (username, password, email) VALUES ('user3','pass3','email3'); + +CREATE TABLE test.user_friends +( + id INTEGER NOT NULL, + friend INTEGER NOT NULL, + PRIMARY KEY (id, friend), + CONSTRAINT FK_user_id FOREIGN KEY (id) + REFERENCES test.users (id) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT FK_friend_id FOREIGN KEY (friend) + REFERENCES test.users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO test.user_friends VALUES (1,2); +INSERT INTO test.user_friends VALUES (1,3); +INSERT INTO test.user_friends VALUES (2,3); + +CREATE TABLE test.profiles +( + id SERIAL NOT NULL PRIMARY KEY, + first_name VARCHAR(128) NOT NULL, + last_name VARCHAR(128) NOT NULL, + user_id INTEGER NOT NULL, + CONSTRAINT FK_profile_user FOREIGN KEY (user_id) + REFERENCES test.users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO test.profiles (first_name, last_name, user_id) VALUES ('first 1','last 1',1); +INSERT INTO test.profiles (first_name, last_name, user_id) VALUES ('first 2','last 2',2); + +CREATE TABLE test.posts +( + id SERIAL NOT NULL PRIMARY KEY, + title VARCHAR(128) NOT NULL, + create_time TIMESTAMP NOT NULL, + author_id INTEGER NOT NULL, + content TEXT, + CONSTRAINT FK_post_author FOREIGN KEY (author_id) + REFERENCES test.users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO test.posts (title, create_time, author_id, content) VALUES ('post 1',TIMESTAMP '2004-10-19 10:23:54',1,'content 1'); +INSERT INTO test.posts (title, create_time, author_id, content) VALUES ('post 2',TIMESTAMP '2004-10-19 10:23:54',2,'content 2'); +INSERT INTO test.posts (title, create_time, author_id, content) VALUES ('post 3',TIMESTAMP '2004-10-19 10:23:54',2,'content 3'); +INSERT INTO test.posts (title, create_time, author_id, content) VALUES ('post 4',TIMESTAMP '2004-10-19 10:23:54',2,'content 4'); +INSERT INTO test.posts (title, create_time, author_id, content) VALUES ('post 5',TIMESTAMP '2004-10-19 10:23:54',3,'content 5'); + +CREATE TABLE test.nullable_posts +( + id SERIAL NOT NULL PRIMARY KEY, + title VARCHAR(128) NULL, + create_time TIMESTAMP NULL, + author_id INTEGER NULL, + content TEXT NULL, + CONSTRAINT FK_post_author FOREIGN KEY (author_id) + REFERENCES test.users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +CREATE TABLE test.comments +( + id SERIAL NOT NULL PRIMARY KEY, + content TEXT NOT NULL, + post_id INTEGER NOT NULL, + author_id INTEGER NOT NULL, + CONSTRAINT FK_post_comment FOREIGN KEY (post_id) + REFERENCES test.posts (id) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT FK_user_comment FOREIGN KEY (author_id) + REFERENCES test.users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 1',1, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 2',1, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 3',1, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 4',2, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 5',2, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 6',3, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 7',3, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 8',3, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 9',3, 2); +INSERT INTO test.comments (content, post_id, author_id) VALUES ('comment 10',5, 3); + +CREATE TABLE test.categories +( + id SERIAL NOT NULL PRIMARY KEY, + name VARCHAR(128) NOT NULL, + parent_id INTEGER, + CONSTRAINT FK_category_category FOREIGN KEY (parent_id) + REFERENCES test.categories (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO test.categories (name, parent_id) VALUES ('cat 1',NULL); +INSERT INTO test.categories (name, parent_id) VALUES ('cat 2',NULL); +INSERT INTO test.categories (name, parent_id) VALUES ('cat 3',NULL); +INSERT INTO test.categories (name, parent_id) VALUES ('cat 4',1); +INSERT INTO test.categories (name, parent_id) VALUES ('cat 5',1); +INSERT INTO test.categories (name, parent_id) VALUES ('cat 6',5); +INSERT INTO test.categories (name, parent_id) VALUES ('cat 7',5); + +CREATE TABLE test.post_category +( + category_id INTEGER NOT NULL, + post_id INTEGER NOT NULL, + PRIMARY KEY (category_id, post_id), + CONSTRAINT FK_post_category_post FOREIGN KEY (post_id) + REFERENCES test.posts (id) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT FK_post_category_category FOREIGN KEY (category_id) + REFERENCES test.categories (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO test.post_category (category_id, post_id) VALUES (1,1); +INSERT INTO test.post_category (category_id, post_id) VALUES (2,1); +INSERT INTO test.post_category (category_id, post_id) VALUES (3,1); +INSERT INTO test.post_category (category_id, post_id) VALUES (4,2); +INSERT INTO test.post_category (category_id, post_id) VALUES (1,2); +INSERT INTO test.post_category (category_id, post_id) VALUES (1,3); + +CREATE TABLE test.orders +( + key1 INTEGER NOT NULL, + key2 INTEGER NOT NULL, + name VARCHAR(128), + PRIMARY KEY (key1, key2) +); + +INSERT INTO test.orders (key1,key2,name) VALUES (1,2,'order 12'); +INSERT INTO test.orders (key1,key2,name) VALUES (1,3,'order 13'); +INSERT INTO test.orders (key1,key2,name) VALUES (2,1,'order 21'); +INSERT INTO test.orders (key1,key2,name) VALUES (2,2,'order 22'); + +CREATE TABLE test.items +( + id SERIAL NOT NULL PRIMARY KEY, + name VARCHAR(128), + col1 INTEGER NOT NULL, + col2 INTEGER NOT NULL, + CONSTRAINT FK_order_item FOREIGN KEY (col1,col2) + REFERENCES test.orders (key1,key2) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO test.items (name,col1,col2) VALUES ('item 1',1,2); +INSERT INTO test.items (name,col1,col2) VALUES ('item 2',1,2); +INSERT INTO test.items (name,col1,col2) VALUES ('item 3',1,3); +INSERT INTO test.items (name,col1,col2) VALUES ('item 4',2,2); +INSERT INTO test.items (name,col1,col2) VALUES ('item 5',2,2); + +CREATE TABLE public.yii_types +( + int_col INT NOT NULL, + int_col2 INTEGER DEFAULT 1, + char_col CHAR(100) NOT NULL, + char_col2 VARCHAR(100) DEFAULT 'something', + char_col3 TEXT, + numeric_col NUMERIC(4,3) NOT NULL, + real_col REAL DEFAULT 1.23, + blob_col BYTEA, + time TIMESTAMP, + bool_col BOOL NOT NULL, + bool_col2 BOOLEAN DEFAULT TRUE +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/sqlite.sql b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/sqlite.sql new file mode 100644 index 0000000..032635f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/data/sqlite.sql @@ -0,0 +1,286 @@ +CREATE TABLE users +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + username VARCHAR(128) NOT NULL, + password VARCHAR(128) NOT NULL, + email VARCHAR(128) NOT NULL +); + +INSERT INTO users(id,username,password,email) VALUES (1,'user1','pass1','email1'); +INSERT INTO users(id,username,password,email) VALUES (2,'user2','pass2','email2'); +INSERT INTO users(id,username,password,email) VALUES (3,'user3','pass3','email3'); +INSERT INTO users(id,username,password,email) VALUES (4,'user4','pass4','email4'); + +CREATE TABLE groups +( + id INTEGER NOT NULL PRIMARY KEY, + name VARCHAR(128) NOT NULL +); + +INSERT INTO groups(id,name) VALUES (1,'group1'); +INSERT INTO groups(id,name) VALUES (2,'group2'); +INSERT INTO groups(id,name) VALUES (3,'group3'); +INSERT INTO groups(id,name) VALUES (4,'group4'); +INSERT INTO groups(id,name) VALUES (5,'group5'); +INSERT INTO groups(id,name) VALUES (6,'group6'); + +CREATE TABLE groups_descriptions +( + group_id INTEGER NOT NULL PRIMARY KEY, + name VARCHAR(128) NOT NULL +); + +INSERT INTO groups_descriptions(group_id,name) VALUES (1,'room1'); +INSERT INTO groups_descriptions(group_id,name) VALUES (2,'room2'); +INSERT INTO groups_descriptions(group_id,name) VALUES (3,'room3'); +INSERT INTO groups_descriptions(group_id,name) VALUES (4,'room4'); + +CREATE TABLE roles +( + user_id INTEGER NOT NULL, + group_id INTEGER NOT NULL, + name VARCHAR(128) NOT NULL, + PRIMARY KEY(user_id,group_id) +); + +INSERT INTO roles(user_id,group_id,name) VALUES (1,1,'dev'); +INSERT INTO roles(user_id,group_id,name) VALUES (1,2,'user'); +INSERT INTO roles(user_id,group_id,name) VALUES (2,1,'dev'); +INSERT INTO roles(user_id,group_id,name) VALUES (2,3,'user'); + +CREATE TABLE mentorships +( + teacher_id INTEGER NOT NULL, + student_id INTEGER NOT NULL, + progress VARCHAR(128) NOT NULL, + PRIMARY KEY(teacher_id,student_id) +); + +INSERT INTO mentorships(teacher_id,student_id,progress) VALUES (1,3,'good'); +INSERT INTO mentorships(teacher_id,student_id,progress) VALUES (2,4,'average'); + +CREATE TABLE profiles +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + first_name VARCHAR(128) NOT NULL, + last_name VARCHAR(128) NOT NULL, + user_id INTEGER NOT NULL, + CONSTRAINT FK_profile_user FOREIGN KEY (user_id) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 1','last 1',1); +INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 2','last 2',2); + +CREATE TABLE posts +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + title VARCHAR(128) NOT NULL, + create_time TIMESTAMP NOT NULL, + author_id INTEGER NOT NULL, + content TEXT, + CONSTRAINT FK_post_author FOREIGN KEY (author_id) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 1',100000,1,'content 1'); +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 2',100001,2,'content 2'); +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 3',100002,2,'content 3'); +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 4',100003,2,'content 4'); +INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 5',100004,3,'content 5'); + + +CREATE TABLE posts_nofk +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + title VARCHAR(128) NOT NULL, + create_time TIMESTAMP NOT NULL, + author_id INTEGER NOT NULL, + content TEXT +); + +INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 1',100000,1,'content 1'); +INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 2',100001,2,'content 2'); +INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 3',100002,2,'content 3'); +INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 4',100003,2,'content 4'); +INSERT INTO posts_nofk (title, create_time, author_id, content) VALUES ('post 5',100004,3,'content 5'); + + +CREATE TABLE comments +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + content TEXT NOT NULL, + post_id INTEGER NOT NULL, + author_id INTEGER NOT NULL, + CONSTRAINT FK_post_comment FOREIGN KEY (post_id) + REFERENCES posts (id) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT FK_user_comment FOREIGN KEY (author_id) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 1',1, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 2',1, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 3',1, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 4',2, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 5',2, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 6',3, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 7',3, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 8',3, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 9',3, 2); +INSERT INTO comments (content, post_id, author_id) VALUES ('comment 10',5, 3); + +CREATE TABLE categories +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + name VARCHAR(128) NOT NULL, + parent_id INTEGER, + CONSTRAINT FK_category_category FOREIGN KEY (parent_id) + REFERENCES categories (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO categories (name, parent_id) VALUES ('cat 1',NULL); +INSERT INTO categories (name, parent_id) VALUES ('cat 2',NULL); +INSERT INTO categories (name, parent_id) VALUES ('cat 3',NULL); +INSERT INTO categories (name, parent_id) VALUES ('cat 4',1); +INSERT INTO categories (name, parent_id) VALUES ('cat 5',1); +INSERT INTO categories (name, parent_id) VALUES ('cat 6',5); +INSERT INTO categories (name, parent_id) VALUES ('cat 7',5); + +CREATE TABLE post_category +( + category_id INTEGER NOT NULL, + post_id INTEGER NOT NULL, + PRIMARY KEY (category_id, post_id), + CONSTRAINT FK_post_category_post FOREIGN KEY (post_id) + REFERENCES posts (id) ON DELETE CASCADE ON UPDATE RESTRICT, + CONSTRAINT FK_post_category_category FOREIGN KEY (category_id) + REFERENCES categories (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO post_category (category_id, post_id) VALUES (1,1); +INSERT INTO post_category (category_id, post_id) VALUES (2,1); +INSERT INTO post_category (category_id, post_id) VALUES (3,1); +INSERT INTO post_category (category_id, post_id) VALUES (4,2); +INSERT INTO post_category (category_id, post_id) VALUES (1,2); +INSERT INTO post_category (category_id, post_id) VALUES (1,3); + +CREATE TABLE orders +( + key1 INTEGER NOT NULL, + key2 INTEGER NOT NULL, + name VARCHAR(128), + PRIMARY KEY (key1, key2) +); + +INSERT INTO orders (key1,key2,name) VALUES (1,2,'order 12'); +INSERT INTO orders (key1,key2,name) VALUES (1,3,'order 13'); +INSERT INTO orders (key1,key2,name) VALUES (2,1,'order 21'); +INSERT INTO orders (key1,key2,name) VALUES (2,2,'order 22'); + +CREATE TABLE items +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + name VARCHAR(128), + col1 INTEGER NOT NULL, + col2 INTEGER NOT NULL, + CONSTRAINT FK_order_item FOREIGN KEY (col1,col2) + REFERENCES orders (key1,key2) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO items (name,col1,col2) VALUES ('item 1',1,2); +INSERT INTO items (name,col1,col2) VALUES ('item 2',1,2); +INSERT INTO items (name,col1,col2) VALUES ('item 3',1,3); +INSERT INTO items (name,col1,col2) VALUES ('item 4',2,2); +INSERT INTO items (name,col1,col2) VALUES ('item 5',2,2); + +CREATE TABLE types +( + int_col INT NOT NULL, + int_col2 INTEGER DEFAULT 1, + char_col CHAR(100) NOT NULL, + char_col2 VARCHAR(100) DEFAULT 'something', + char_col3 TEXT, + char_col4 VARCHAR(100) DEFAULT NULL, + char_col5 VARCHAR(100) DEFAULT 'NULL', + float_col REAL(4,3) NOT NULL, + float_col2 DOUBLE DEFAULT 1.23, + blob_col BLOB, + numeric_col NUMERIC(5,2) DEFAULT 33.22, + time TIMESTAMP DEFAULT 123, + bool_col BOOL NOT NULL, + bool_col2 BOOLEAN DEFAULT 1, + null_col INTEGER DEFAULT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE Content +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + class VARCHAR(128), + parentID INTEGER NOT NULL, + ownerID INTEGER NOT NULL, + title VARCHAR(100), + CONSTRAINT FK_content_user FOREIGN KEY (ownerID) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT + CONSTRAINT FK_content_parent FOREIGN KEY (parentID) + REFERENCES Content (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Article',-1,1,'article 1'); +INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Article',-1,2,'article 2'); +INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Comment',1,1,'comment 1'); +INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Article',-1,2,'article 3'); +INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Comment',4,2,'comment 2'); +INSERT INTO Content (class,parentID,ownerID,title) VALUES ('Comment',4,1,'comment 3'); + +CREATE TABLE Article +( + id INTEGER NOT NULL PRIMARY KEY, + authorID INTEGER NOT NULL, + body TEXT, + CONSTRAINT FK_article_content FOREIGN KEY (id) + REFERENCES Content (id) ON DELETE CASCADE ON UPDATE RESTRICT + CONSTRAINT FK_article_author FOREIGN KEY (authorID) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO Article (id,authorID,body) VALUES (1,1,'content for article 1'); +INSERT INTO Article (id,authorID,body) VALUES (2,2,'content for article 2'); +INSERT INTO Article (id,authorID,body) VALUES (4,1,'content for article 3'); + +CREATE TABLE Comment +( + id INTEGER NOT NULL PRIMARY KEY, + authorID INTEGER NOT NULL, + body TEXT, + CONSTRAINT FK_comment_content FOREIGN KEY (id) + REFERENCES Content (id) ON DELETE CASCADE ON UPDATE RESTRICT + CONSTRAINT FK_article_author FOREIGN KEY (authorID) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT +); + +INSERT INTO Comment (id,authorID,body) VALUES (3,1,'content for comment 1'); +INSERT INTO Comment (id,authorID,body) VALUES (5,1,'content for comment 2'); +INSERT INTO Comment (id,authorID,body) VALUES (6,1,'content for comment 3'); + +CREATE TABLE UserWithDefaultScope +( + id INTEGER NOT NULL PRIMARY KEY, + deleted INTEGER DEFAULT NULL, + `name` VARCHAR(255) NOT NULL +); + +INSERT INTO UserWithDefaultScope (id,deleted,`name`) VALUES (1,NULL,'Fred Bloggs'); +INSERT INTO UserWithDefaultScope (id,deleted,`name`) VALUES (2,NULL,'Joe Bloggs'); +INSERT INTO UserWithDefaultScope (id,deleted,`name`) VALUES (3,1,'Jane Bloggs'); + +CREATE TABLE UserWithDefaultScopeLink +( + id INTEGER NOT NULL PRIMARY KEY, + from_id INTEGER NOT NULL, + to_id INTEGER NOT NULL +); + +INSERT INTO UserWithDefaultScopeLink (id,from_id,to_id) VALUES (1,1,2); +INSERT INTO UserWithDefaultScopeLink (id,from_id,to_id) VALUES (2,2,3); +INSERT INTO UserWithDefaultScopeLink (id,from_id,to_id) VALUES (3,3,1); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CDbCriteriaTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CDbCriteriaTest.php new file mode 100644 index 0000000..df5517b --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CDbCriteriaTest.php @@ -0,0 +1,638 @@ +addCondition('A'); + $this->assertEquals('A', $criteria->condition); + + //adding multiple conditions + $criteria = new CDbCriteria(); + $criteria->addCondition('A'); + $criteria->addCondition('B'); + $criteria->addCondition('C', 'OR'); + $this->assertEquals('((A) AND (B)) OR (C)', $criteria->condition); + + //adding empty array as condition + $criteria = new CDbCriteria(); + $criteria->addCondition('A'); + $criteria->addCondition(array()); + $this->assertEquals('A', $criteria->condition); + + //adding array as condition + $criteria = new CDbCriteria(); + $criteria->addCondition(array('A', 'B')); + $this->assertEquals('(A) AND (B)', $criteria->condition); + } + + /** + * @depends testAddCondition + * @covers CDbCriteria::addInCondition + */ + public function testAddInCondition() { + CDbCriteria::$paramCount=0; + $criteria = new CDbCriteria(); + + $criteria->addInCondition('A', array()); + $this->assertEquals('0=1', $criteria->condition); + $this->assertTrue(empty($criteria->params)); + + // IN with one parameter should transform to = + $criteria = new CDbCriteria(); + + $criteria->addInCondition('A', array(1)); + $this->assertEquals('A=:ycp0', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp0']); + + // IN with null should transform to IS NULL + $criteria = new CDbCriteria(); + + $criteria->addInCondition('A', array(null)); + $this->assertEquals('A IS NULL', $criteria->condition); + $this->assertTrue(empty($criteria->params)); + + // IN with many parameters + $criteria = new CDbCriteria(); + + $criteria->addInCondition('B', array(1, 2, '3')); + $this->assertEquals('B IN (:ycp1, :ycp2, :ycp3)', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp1']); + $this->assertEquals(2, $criteria->params[':ycp2']); + $this->assertEquals('3', $criteria->params[':ycp3']); + } + + /** + * @depends testAddCondition + * @covers CDbCriteria::addNotInCondition + */ + public function testAddNotInCondition() { + // NOT IN with empty array should not change anything + CDbCriteria::$paramCount=0; + $criteria = new CDbCriteria(); + + $criteria->addNotInCondition('A', array()); + $this->assertEquals('', $criteria->condition); + $this->assertTrue(empty($criteria->params)); + + // NOT IN with one parameter should transform to != + $criteria = new CDbCriteria(); + + $criteria->addNotInCondition('A', array(1)); + $this->assertEquals('A!=:ycp0', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp0']); + + // NOT IN with null should transform to IS NOT NULL + $criteria = new CDbCriteria(); + + $criteria->addNotInCondition('A', array(null)); + $this->assertEquals('A IS NOT NULL', $criteria->condition); + $this->assertTrue(empty($criteria->params)); + + // NOT IN with many parameters + $criteria = new CDbCriteria(); + + $criteria->addNotInCondition('B', array(1, 2, '3')); + $this->assertEquals('B NOT IN (:ycp1, :ycp2, :ycp3)', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp1']); + $this->assertEquals(2, $criteria->params[':ycp2']); + $this->assertEquals('3', $criteria->params[':ycp3']); + } + + /** + * @depends testAddCondition + * @covers CDbCriteria::addSearchCondition + */ + public function testAddSearchCondition() { + // string escaping + CDbCriteria::$paramCount=0; + $criteria = new CDbCriteria(); + $criteria->addSearchCondition('A', 'key_word%'); + + $this->assertEquals('A LIKE :ycp0', $criteria->condition); + $this->assertEquals('%key\_word\%%', $criteria->params[':ycp0']); + + // no escaping + $criteria = new CDbCriteria(); + $criteria->addSearchCondition('A', 'key_word%', false); + + $this->assertEquals('A LIKE :ycp1', $criteria->condition); + $this->assertEquals('key_word%', $criteria->params[':ycp1']); + } + + /** + * @depends testAddCondition + * @covers CDbCriteria::addColumnCondition + */ + public function testAddColumnCondition() { + CDbCriteria::$paramCount=0; + $criteria = new CDbCriteria(); + $criteria->addColumnCondition(array('A' => 1, 'B' => null, 'C' => '2')); + + $this->assertEquals('A=:ycp0 AND B IS NULL AND C=:ycp1', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp0']); + $this->assertEquals('2', $criteria->params[':ycp1']); + } + + /** + * @depends testAddCondition + * @covers CDbCriteria::compare + */ + public function testCompare(){ + CDbCriteria::$paramCount=0; + $criteria = new CDbCriteria(); + $criteria->compare('A', ''); + $this->assertEquals('', $criteria->condition); + + $criteria = new CDbCriteria(); + $criteria->compare('A', 1); + $this->assertEquals('A=:ycp0', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp0']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '>1'); + $this->assertEquals('A>:ycp1', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp1']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '<1'); + $this->assertEquals('A<:ycp2', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp2']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '<=1'); + $this->assertEquals('A<=:ycp3', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp3']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '>=1'); + $this->assertEquals('A>=:ycp4', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp4']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '<>1'); + $this->assertEquals('A<>:ycp5', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp5']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '=1'); + $this->assertEquals('A=:ycp6', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp6']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '1', true); + $this->assertEquals('A LIKE :ycp7', $criteria->condition); + $this->assertEquals('%1%', $criteria->params[':ycp7']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '=1', true); + $this->assertEquals('A=:ycp8', $criteria->condition); + $this->assertEquals('1', $criteria->params[':ycp8']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', '<>1', true); + $this->assertEquals('A NOT LIKE :ycp9', $criteria->condition); + $this->assertEquals('%1%', $criteria->params[':ycp9']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', ' value_with_spaces '); + $this->assertEquals('A=:ycp10', $criteria->condition); + $this->assertEquals(' value_with_spaces ', $criteria->params[':ycp10']); + + $criteria = new CDbCriteria(); + $criteria->compare('A', array()); + $this->assertEquals('', $criteria->condition); + + $criteria = new CDbCriteria(); + $criteria->compare('A', array(1, '2')); + $this->assertEquals('A IN (:ycp11, :ycp12)', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp11']); + $this->assertEquals('2', $criteria->params[':ycp12']); + } + + /** + * @depends testCompare + * @covers CDbCriteria::mergeWith + */ + public function testMergeWith() { + // merging select + + // * should be replaced + CDbCriteria::$paramCount=0; + $criteria1 = new CDbCriteria; + $criteria1->select = '*'; + + $criteria2 = new CDbCriteria; + $criteria2->select = 'a'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('a', $criteria1->select); + + // equal selects should be left as is + $criteria1 = new CDbCriteria; + $criteria1->select = 'a'; + + $criteria2 = new CDbCriteria; + $criteria2->select = 'a'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('a', $criteria1->select); + + // not equal selects are being merged + $criteria1 = new CDbCriteria; + $criteria1->select = 'a, b, c, d'; + + $criteria2 = new CDbCriteria; + $criteria2->select = 'a, c, e, f'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array('a', 'b', 'c', 'd', 'e', 'f'), $criteria1->select); + + // conditions + + // equal conditions are not merged + $criteria1 = new CDbCriteria; + $criteria1->condition = 'a'; + + $criteria2 = new CDbCriteria; + $criteria2->condition = 'a'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('a', $criteria1->condition); + + // empty condition is being replaced + $criteria1 = new CDbCriteria; + $criteria1->condition = ''; + + $criteria2 = new CDbCriteria; + $criteria2->condition = 'a'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('a', $criteria1->condition); + + // not empty conditions are merged + $criteria1 = new CDbCriteria; + $criteria1->condition = 'a'; + + $criteria2 = new CDbCriteria; + $criteria2->condition = 'b'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('(a) AND (b)', $criteria1->condition); + + // limit, offset, distinct and alias are being replaced + $criteria1 = new CDbCriteria; + $criteria1->limit = 10; + $criteria1->offset = 5; + $criteria1->alias = 'alias1'; + $criteria1->distinct = true; + + $criteria2 = new CDbCriteria; + $criteria2->limit = 20; + $criteria2->offset = 6; + $criteria2->alias = 'alias2'; + $criteria1->distinct = false; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(20, $criteria1->limit); + $this->assertEquals(6, $criteria1->offset); + $this->assertEquals('alias2', $criteria1->alias); + $this->assertFalse($criteria1->distinct); + + + // empty order, group, join, having are being replaced + $criteria1 = new CDbCriteria; + $criteria1->order = ''; + $criteria1->group = ''; + $criteria1->join = ''; + $criteria1->having = ''; + + $criteria2 = new CDbCriteria; + $criteria2->order = 'a'; + $criteria1->group = 'a'; + $criteria1->join = 'a'; + $criteria2->having = 'a'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('a', $criteria1->order); + $this->assertEquals('a', $criteria1->group); + $this->assertEquals('a', $criteria1->join); + $this->assertEquals('a', $criteria1->having); + + // merging with empty order, group, join ignored + $criteria1 = new CDbCriteria; + $criteria1->order = 'a'; + $criteria1->group = 'a'; + $criteria1->join = 'a'; + $criteria1->having = 'a'; + + $criteria2 = new CDbCriteria; + $criteria2->order = ''; + $criteria2->group = ''; + $criteria2->join = ''; + $criteria2->having = ''; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('a', $criteria1->order); + $this->assertEquals('a', $criteria1->group); + $this->assertEquals('a', $criteria1->join); + $this->assertEquals('a', $criteria1->having); + + // not empty order, group, join are being merged + $criteria1 = new CDbCriteria; + $criteria1->order = 'a'; + $criteria1->group = 'a'; + $criteria1->join = 'a'; + $criteria1->having = 'a'; + + $criteria2 = new CDbCriteria; + $criteria2->order = 'b'; + $criteria2->group = 'b'; + $criteria2->join = 'b'; + $criteria2->having = 'b'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('b, a', $criteria1->order); + $this->assertEquals('a, b', $criteria1->group); + $this->assertEquals('a b', $criteria1->join); + $this->assertEquals('(a) AND (b)', $criteria1->having); + + // empty with is replaced + $criteria1 = new CDbCriteria; + $criteria1->with = ''; + + $criteria2 = new CDbCriteria; + $criteria2->with = 'a'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('a', $criteria1->with); + + // not empty with are merged + $criteria1 = new CDbCriteria; + $criteria1->with = 'a'; + + $criteria2 = new CDbCriteria; + $criteria2->with = 'b'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array('a', 'b'), $criteria1->with); + + // not empty with are merged (more complex test) + $criteria1 = new CDbCriteria; + $criteria1->with = array('a', 'b'); + + $criteria2 = new CDbCriteria; + $criteria2->with = array('a', 'c'); + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array('a', 'b', 'a', 'c'), $criteria1->with); + + // merging scopes + $criteria1=new CDbCriteria; + $criteria1->scopes='scope1'; + + $criteria2=new CDbCriteria; + $criteria2->scopes='scope2'; + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array('scope1','scope2'),$criteria1->scopes); + + $criteria1=new CDbCriteria; + $criteria1->scopes='scope1'; + + $criteria2=new CDbCriteria; + $criteria2->scopes=array('scope2'=>1); + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array('scope1','scope2'=>1),$criteria1->scopes); + + $criteria1=new CDbCriteria; + $criteria1->scopes=array('scope1'=>array(1,2)); + + $criteria2=new CDbCriteria; + $criteria2->scopes=array('scope2'=>array(3,4)); + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array('scope1'=>array(1,2),'scope2'=>array(3,4)),$criteria1->scopes); + + $criteria1=new CDbCriteria; + $criteria1->scopes=array('scope'=>array(1,2)); + + $criteria2=new CDbCriteria; + $criteria2->scopes=array('scope'=>array(3,4)); + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array(array('scope'=>array(1,2)),array('scope'=>array(3,4))),$criteria1->scopes); + + $criteria1=new CDbCriteria; + $criteria1->scopes=array('scope'=>array(1,2),'scope1'); + + $criteria2=new CDbCriteria; + $criteria2->scopes=array('scope2','scope'=>array(3,4)); + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array(array('scope'=>array(1,2)),'scope1','scope2',array('scope'=>array(3,4))),$criteria1->scopes); + + $criteria1=new CDbCriteria; + $criteria1->scopes=array(array('scope'=>array(1,2)),array('scope'=>array(3,4))); + + $criteria2=new CDbCriteria; + $criteria2->scopes=array(array('scope'=>array(5,6)),array('scope'=>array(7,8))); + + $criteria1->mergeWith($criteria2); + + $this->assertEquals(array(array('scope'=>array(1,2)),array('scope'=>array(3,4)),array('scope'=>array(5,6)),array('scope'=>array(7,8))),$criteria1->scopes); + + // merging two criteria with parameters + $criteria1 = new CDbCriteria; + $criteria1->compare('A1', 1); + $criteria1->compare('A2', 2); + $criteria1->compare('A3', 3); + $criteria1->compare('A4', 4); + $criteria1->compare('A5', 5); + $criteria1->compare('A6', 6); + + $criteria2 = new CDbCriteria; + $criteria2->compare('B1', 7); + $criteria2->compare('B2', 8); + $criteria2->compare('B3', 9); + $criteria2->compare('B4', 10); + $criteria2->compare('B5', 11); + $criteria2->compare('B6', 12); + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('((((((A1=:ycp0) AND (A2=:ycp1)) AND (A3=:ycp2)) AND (A4=:ycp3)) AND (A5=:ycp4)) AND (A6=:ycp5)) AND ((((((B1=:ycp6) AND (B2=:ycp7)) AND (B3=:ycp8)) AND (B4=:ycp9)) AND (B5=:ycp10)) AND (B6=:ycp11))', $criteria1->condition); + $this->assertEquals(1, $criteria1->params[':ycp0']); + $this->assertEquals(2, $criteria1->params[':ycp1']); + $this->assertEquals(3, $criteria1->params[':ycp2']); + $this->assertEquals(4, $criteria1->params[':ycp3']); + $this->assertEquals(5, $criteria1->params[':ycp4']); + $this->assertEquals(6, $criteria1->params[':ycp5']); + $this->assertEquals(7, $criteria1->params[':ycp6']); + $this->assertEquals(8, $criteria1->params[':ycp7']); + $this->assertEquals(9, $criteria1->params[':ycp8']); + $this->assertEquals(10, $criteria1->params[':ycp9']); + $this->assertEquals(11, $criteria1->params[':ycp10']); + $this->assertEquals(12, $criteria1->params[':ycp11']); + } + + /** + * Merging criterias with positioned and non positioned parameters. + * + * @depends testCompare + * @covers CDbCriteria::mergeWith + */ + public function testMergeWithPositionalPlaceholders(){ + CDbCriteria::$paramCount=0; + $criteria1 = new CDbCriteria(); + $criteria1->condition = 'A=? AND B=?'; + $criteria1->params = array(0 => 10, 1 => 20); + + $criteria2 = new CDbCriteria(); + $criteria2->compare('C', 30); + $criteria2->compare('D', 40); + + $criteria2->mergeWith($criteria1); + + $this->assertEquals('((C=:ycp0) AND (D=:ycp1)) AND (A=? AND B=?)', $criteria2->condition); + + $this->assertEquals(10, $criteria2->params[0]); + $this->assertEquals(20, $criteria2->params[1]); + $this->assertEquals(30, $criteria2->params[':ycp0']); + $this->assertEquals(40, $criteria2->params[':ycp1']); + + // and vice versa + + $criteria1 = new CDbCriteria(); + $criteria1->condition = 'A=? AND B=?'; + $criteria1->params = array(0 => 10, 1 => 20); + + $criteria2 = new CDbCriteria(); + $criteria2->compare('C', 30); + $criteria2->compare('D', 40); + + $criteria1->mergeWith($criteria2); + + $this->assertEquals('(A=? AND B=?) AND ((C=:ycp2) AND (D=:ycp3))', $criteria1->condition); + $this->assertEquals(10, $criteria1->params[0]); + $this->assertEquals(20, $criteria1->params[1]); + $this->assertEquals(30, $criteria1->params[':ycp2']); + $this->assertEquals(40, $criteria1->params[':ycp3']); + } + + /** + * @covers CDbCriteria::addBetweenCondition + */ + public function testAddBetweenCondition(){ + CDbCriteria::$paramCount=0; + $criteria = new CDbCriteria(); + + $criteria->addBetweenCondition('A', 1, 2); + $this->assertEquals('A BETWEEN :ycp0 AND :ycp1', $criteria->condition); + $this->assertEquals(1, $criteria->params[':ycp0']); + $this->assertEquals(2, $criteria->params[':ycp1']); + } + + public function testToArray(){ + $keys = array('select', 'condition', 'params', 'limit', 'offset', 'order', 'group', 'join', 'having', 'distinct', 'scopes', 'with', 'alias', 'index', 'together'); + $criteria = new CDbCriteria(); + $this->assertEquals($keys, array_keys($criteria->toArray())); + } + + public function testSerialize() + { + $criteria = new CDbCriteria(); + + $fieldName='testFieldName'; + $paramName=':testParamName'; + $paramValue='testParamValue'; + $criteria->condition="{$fieldName} = {$paramName}"; + $criteria->order="{$paramName}"; + $criteria->group="{$paramName}"; + $criteria->having="{$paramName}"; + $criteria->select="{$paramName}"; + $criteria->params[$paramName]=$paramValue; + + $serializedCriteria=serialize($criteria); + $unserializedCriteria=unserialize($serializedCriteria); + + $this->assertEquals($criteria,$unserializedCriteria,'Criteria has wrong data after wakeup!'); + } + + /** + * @depends testSerialize + */ + public function testSerializeAutomaticallyGeneratedParams() + { + $criteria = new CDbCriteria(); + $paramName=CDbCriteria::PARAM_PREFIX.rand(10000,20000); // mock up automatically generated name + $paramValue = 'testParamValue'; + $criteria->condition="someField = {$paramName}"; + $criteria->order="{$paramName}"; + $criteria->group="{$paramName}"; + $criteria->having="{$paramName}"; + $criteria->select="{$paramName}"; + $criteria->params[$paramName]=$paramValue; + + $serializedCriteria=serialize($criteria); + $unserializedCriteria=unserialize($serializedCriteria); + + $this->assertArrayNotHasKey($paramName,$unserializedCriteria->params,'Param name which match automatic generation has not been replaced!'); + $this->assertContains($paramValue,$unserializedCriteria->params,'Automatically generated param value has been lost!'); + + $newParamName = array_search($paramValue,$unserializedCriteria->params,true); + $this->assertEquals(str_replace($paramName,$newParamName,$criteria->condition),$unserializedCriteria->condition,'Criteria condition has not been updated!'); + $this->assertEquals(str_replace($paramName,$newParamName,$criteria->order),$unserializedCriteria->order,'Criteria order has not been updated!'); + $this->assertEquals(str_replace($paramName,$newParamName,$criteria->group),$unserializedCriteria->group,'Criteria group has not been updated!'); + $this->assertEquals(str_replace($paramName,$newParamName,$criteria->having),$unserializedCriteria->having,'Criteria having has not been updated!'); + $this->assertEquals(str_replace($paramName,$newParamName,$criteria->select),$unserializedCriteria->select,'Criteria select has not been updated!'); + } + + /** + * https://github.com/yiisoft/yii/issues/2426 + */ + public function testWakeupWhenSqlContainingFieldsAreArraysWithSpecifiedParams() + { + CDbCriteria::$paramCount=10; + $criteria=new CDbCriteria(); + $criteria->select=array('id','title'); + $criteria->condition='id=:postId'; + $criteria->params['postId']=1; + $criteria->compare('authorId',2); + + $oldCriteria=clone $criteria; + + $criteria=serialize($criteria); + CDbCriteria::$paramCount=10; + $criteria=unserialize($criteria); + + $this->assertEquals($oldCriteria,$criteria); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMssqlTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMssqlTest.php new file mode 100644 index 0000000..6a9341a --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMssqlTest.php @@ -0,0 +1,399 @@ +markTestSkipped('PDO and SQLSRV extensions are required.'); + else if(self::DB_DSN_PREFIX!='sqlsrv' && (!extension_loaded('pdo') || !extension_loaded('pdo_dblib'))) + $this->markTestSkipped('PDO and MSSQL extensions are required.'); + + if(self::DB_DSN_PREFIX=='sqlsrv') + $dsn=self::DB_DSN_PREFIX.':Server='.self::DB_HOST.';Database='.self::DB_NAME; + else + $dsn=self::DB_DSN_PREFIX.':host='.self::DB_HOST.';dbname='.self::DB_NAME; + + $this->db=new CDbConnection($dsn,self::DB_USER,self::DB_PASS); + if(self::DB_DSN_PREFIX=='sqlsrv') + $this->db->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM); + try + { + $this->db->active=true; + } + catch(Exception $e) + { + $schemaFile=realpath(dirname(__FILE__).'/../data/mssql.sql'); + $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for MSSQL test case."); + } + + $tables=array('comments','post_category','posts','categories','profiles','users','items','orders','types'); + foreach($tables as $table) + { + $sql=<<db->createCommand($sql)->execute(); + } + + $rawSqls=file_get_contents(dirname(__FILE__).'/../data/mssql.sql'); + + // remove comments from SQL + $sqls=''; + foreach(array_filter(explode("\n", $rawSqls)) as $line) + { + if(substr($line,0,2)=='--') + continue; + $sqls.=$line."\n"; + } + + // run SQL + foreach(explode('GO',$sqls) as $sql) + { + if(trim($sql)!=='') + $this->db->createCommand($sql)->execute(); + } + + CActiveRecord::$db=$this->db; + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testSchema() + { + $schema=$this->db->schema; + $this->assertTrue($schema instanceof CDbSchema); + $this->assertEquals($schema->dbConnection,$this->db); + $this->assertTrue($schema->commandBuilder instanceof CDbCommandBuilder); + $this->assertEquals('[posts]',$schema->quoteTableName('posts')); + $this->assertEquals('[dbo].[posts]',$schema->quoteTableName('dbo.posts')); + $this->assertEquals('[id]',$schema->quoteColumnName('id')); + $this->assertTrue($schema->getTable('posts') instanceof CDbTableSchema); + $this->assertNull($schema->getTable('foo')); + } + + public function testTable() + { + $table=$this->db->schema->getTable('posts'); + $this->assertTrue($table instanceof CDbTableSchema); + $this->assertEquals('posts',$table->name); + $this->assertEquals('dbo',$table->schemaName); + $this->assertEquals('[dbo].[posts]',$table->rawName); + $this->assertEquals('id',$table->primaryKey); + $this->assertEquals(array('author_id'=>array('users','id')),$table->foreignKeys); + $this->assertEquals('posts',$table->sequenceName); + $this->assertEquals(5,count($table->columns)); + + $this->assertTrue($table->getColumn('id') instanceof CDbColumnSchema); + $this->assertTrue($table->getColumn('foo')===null); + $this->assertEquals(array('id','title','create_time','author_id','content'),$table->columnNames); + + $table=$this->db->schema->getTable('orders'); + $this->assertEquals(array('key1','key2'),$table->primaryKey); + + $table=$this->db->schema->getTable('items'); + $this->assertEquals('id',$table->primaryKey); + $this->assertEquals(array('col1'=>array('orders','key1'),'col2'=>array('orders','key2')),$table->foreignKeys); + + $table=$this->db->schema->getTable('types'); + $this->assertTrue($table instanceof CDbTableSchema); + $this->assertEquals('types',$table->name); + $this->assertEquals('[dbo].[types]',$table->rawName); + $this->assertTrue($table->primaryKey===null); + $this->assertTrue($table->foreignKeys===array()); + $this->assertTrue($table->sequenceName===null); + + $table=$this->db->schema->getTable('invalid'); + $this->assertNull($table); + } + + public function testColumn() + { + $values=array( + 'name'=>array('id', 'title', 'create_time', 'author_id', 'content'), + 'rawName'=>array('[id]', '[title]', '[create_time]', '[author_id]', '[content]'), + 'defaultValue'=>array(null, null, null, null, null), + 'size'=>array(10, 128, null, 10, null), + 'precision'=>array(10, 128, null, 10, null), + 'scale'=>array(0, null, null, 0, null), + 'dbType'=>array('int','varchar','datetime','int','text'), + 'type'=>array('integer','string','string','integer','string'), + 'isPrimaryKey'=>array(true,false,false,false,false), + 'isForeignKey'=>array(false,false,false,true,false), + ); + $this->checkColumns('posts',$values); + $values=array( + 'name'=>array('int_col', 'int_col2', 'char_col', 'char_col2', 'char_col3', 'float_col', 'float_col2', 'blob_col', 'numeric_col', 'time', 'bool_col', 'bool_col2'), + 'rawName'=>array('[int_col]', '[int_col2]', '[char_col]', '[char_col2]', '[char_col3]', '[float_col]', '[float_col2]', '[blob_col]', '[numeric_col]', '[time]', '[bool_col]', '[bool_col2]'), + 'defaultValue'=>array(null, 1, null, "something", null, null, '1.23', null, '33.22', '2002-01-01 00:00:00', null, true), + 'size'=>array(10, 10, 100, 100, null, 24, 53, null, 5, null, null, null), + 'precision'=>array(10, 10, 100, 100, null, 24, 53, null, 5, null, null, null), + 'scale'=>array(0, 0, null, null, null, null, null, null, 2, null, null, null), + 'dbType'=>array('int','int','char','varchar','text','real','float','image','numeric','datetime','bit','bit'), + 'type'=>array('integer','integer','string','string','string','double','double','string','string','string','boolean','boolean'), + 'isPrimaryKey'=>array(false,false,false,false,false,false,false,false,false,false,false,false), + 'isForeignKey'=>array(false,false,false,false,false,false,false,false,false,false,false,false), + ); + $this->checkColumns('types',$values); + } + + protected function checkColumns($tableName,$values) + { + $table=$this->db->schema->getTable($tableName); + foreach($values as $name=>$value) + { + foreach(array_values($table->columns) as $i=>$column) + { + $type1=gettype($column->$name); + $type2=gettype($value[$i]); + $this->assertTrue($column->$name==$value[$i], "$tableName.{$column->name}.$name is {$column->$name} ($type1), different from the expected {$value[$i]} ($type2)."); + } + } + } + + public function testCommandBuilder() + { + $schema=$this->db->schema; + $builder=$schema->commandBuilder; + $this->assertTrue($builder instanceof CDbCommandBuilder); + $table=$schema->getTable('posts'); + + $c=$builder->createInsertCommand($table,array('title'=>'test post','create_time'=>'2000-01-01','author_id'=>1,'content'=>'test content')); + $this->assertEquals('INSERT INTO [dbo].[posts] ([title], [create_time], [author_id], [content]) VALUES (:yp0, :yp1, :yp2, :yp3)',$c->text); + $c->execute(); + $this->assertEquals(6,$builder->getLastInsertId($table)); + $this->assertEquals(6, $this->db->getLastInsertID()); + + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals('SELECT COUNT(*) FROM [dbo].[posts] [t]',$c->text); + $this->assertEquals(6,$c->queryScalar()); + + $c=$builder->createDeleteCommand($table,new CDbCriteria(array( + 'condition'=>'id=:id', + 'params'=>array('id'=>6)))); + $this->assertEquals('DELETE FROM [dbo].[posts] WHERE id=:id',$c->text); + $c->execute(); + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals(5,$c->queryScalar()); + + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'id, title', + 'condition'=>'id=:id', + 'params'=>array('id'=>5), + 'order'=>'title', + 'limit'=>2, + 'offset'=>0))); + $this->assertEquals('SELECT TOP 2 id, title FROM [dbo].[posts] [t] WHERE id=:id ORDER BY title',$c->text); + $rows=$c->query()->readAll(); + $this->assertEquals(1,count($rows)); + $this->assertEquals('post 5',$rows[0]['title']); + + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'id, title', + 'order'=>'title', + 'limit'=>2, + 'offset'=>3))); + $this->assertEquals('SELECT * FROM (SELECT TOP 2 * FROM (SELECT TOP 5 id, title FROM [dbo].[posts] [t] ORDER BY title) as [__inner__] ORDER BY title DESC) as [__outer__] ORDER BY title ASC',$c->text); + $rows=$c->query()->readAll(); + $this->assertEquals(2,count($rows)); + $this->assertEquals('post 4',$rows[0]['title']); + + $c=$builder->createUpdateCommand($table,array('title'=>'new post 5'),new CDbCriteria(array( + 'condition'=>'id=:id', + 'params'=>array('id'=>5)))); + $c->execute(); + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=:id', + 'params'=>array('id'=>5)))); + $this->assertEquals('new post 5',$c->queryScalar()); + + $c=$builder->createSqlCommand('SELECT title FROM posts WHERE id=:id',array(':id'=>3)); + $this->assertEquals('post 3',$c->queryScalar()); + + $c=$builder->createUpdateCounterCommand($table,array('author_id'=>-2),new CDbCriteria(array('condition'=>'id=5'))); + $this->assertEquals('UPDATE [dbo].[posts] SET [author_id]=[author_id]-2 WHERE id=5',$c->text); + $c->execute(); + $c=$builder->createSqlCommand('SELECT author_id FROM posts WHERE id=5'); + $this->assertEquals(1,$c->queryScalar()); + + // test bind by position + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=?', + 'params'=>array(4)))); + $this->assertEquals('SELECT title FROM [dbo].[posts] [t] WHERE id=?',$c->text); + $this->assertEquals('post 4',$c->queryScalar()); + + // another bind by position + $c=$builder->createUpdateCommand($table,array('title'=>'new post 4'),new CDbCriteria(array( + 'condition'=>'id=?', + 'params'=>array(4)))); + $c->execute(); + $c=$builder->createSqlCommand('SELECT title FROM posts WHERE id=4'); + $this->assertEquals('new post 4',$c->queryScalar()); + + // testCreateCriteria + $c=$builder->createCriteria('column=:value',array(':value'=>'value')); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c=$builder->createCriteria(array('condition'=>'column=:value','params'=>array(':value'=>'value'))); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c2=$builder->createCriteria($c); + $this->assertTrue($c2!==$c); + $this->assertEquals('column=:value',$c2->condition); + $this->assertEquals(array(':value'=>'value'),$c2->params); + + // testCreatePkCriteria + $c=$builder->createPkCriteria($table,1,'author_id>1'); + $this->assertEquals('[dbo].[posts].[id]=1 AND (author_id>1)',$c->condition); + + $c=$builder->createPkCriteria($table,array(1,2)); + $this->assertEquals('[dbo].[posts].[id] IN (1, 2)',$c->condition); + + $c=$builder->createPkCriteria($table,array()); + $this->assertEquals('0=1',$c->condition); + + $table2=$schema->getTable('orders'); + $c=$builder->createPkCriteria($table2,array('key1'=>1,'key2'=>2),'name=\'\''); + $this->assertEquals('[dbo].[orders].[key1]=1 AND [dbo].[orders].[key2]=2 AND (name=\'\')',$c->condition); + + $c=$builder->createPkCriteria($table2,array(array('key1'=>1,'key2'=>2),array('key1'=>3,'key2'=>4))); + $this->assertEquals('(([dbo].[orders].[key1]=1 AND [dbo].[orders].[key2]=2) OR ([dbo].[orders].[key1]=3 AND [dbo].[orders].[key2]=4))',$c->condition); + + // createColumnCriteria + $c=$builder->createColumnCriteria($table,array('id'=>1,'author_id'=>2),'title=\'\''); + $this->assertEquals('[dbo].[posts].[id]=:yp0 AND [dbo].[posts].[author_id]=:yp1 AND (title=\'\')',$c->condition); + + $c=$builder->createPkCriteria($table2,array()); + $this->assertEquals('0=1',$c->condition); + } + + public function testTransactions() + { + $transaction=$this->db->beginTransaction(); + $schema=$this->db->schema; + $builder=$schema->commandBuilder; + $table=$schema->getTable('posts'); + + // Working transaction + try + { + $builder->createInsertCommand($table, array('title'=>'working transaction test post 1','create_time'=>'2009-01-01','author_id'=>1,'content'=>'test content'))->execute(); + $builder->createInsertCommand($table, array('title'=>'working transaction test post 2','create_time'=>'2009-01-01','author_id'=>1,'content'=>'test content'))->execute(); + $transaction->commit(); + } + catch (Exception $e) + { + $transaction->rollback(); + } + $n=$builder->createCountCommand($table, new CDbCriteria(array('condition' => "title LIKE 'working transaction%'")))->queryScalar(); + $this->assertEquals(2, $n); + + // Failing Transaction + $transaction=$this->db->beginTransaction(); + try + { + $builder->createInsertCommand($table, array('title'=>'failed transaction test post 1','create_time'=>'2009-01-01','author_id'=>1,'content'=>'test content'))->execute(); + $builder->createInsertCommand($table, array('id' => 1, 'title'=>'failed transaction test post 2','create_time'=>'2009-01-01','author_id'=>1,'content'=>'test content'))->execute(); + $transaction->commit(); + } + catch (Exception $e) + { + $transaction->rollback(); + } + $n=$builder->createCountCommand($table, new CDbCriteria(array('condition' => "title LIKE 'failed transaction%'")))->queryScalar(); + $this->assertEquals(0, $n); + } + + public function testColumnComments() + { + $tables=$this->db->schema->tables; + + $usersColumns=$tables['users']->columns; + $this->assertEquals('Name of the user', $usersColumns['username']->comment); + $this->assertEquals('User\'s password', $usersColumns['password']->comment); + $this->assertEquals('User\'s email', $usersColumns['email']->comment); + + $usersColumns=$tables['profiles']->columns; + $this->assertEquals('用户å。', $usersColumns['first_name']->comment); + $this->assertEquals('ТеÑÑ‚ Юникода', $usersColumns['id']->comment); + $this->assertEquals('User\'s identifier', $usersColumns['user_id']->comment); + $this->assertEmpty($usersColumns['last_name']->comment); + } + + public function testARLastInsertId() + { + $user=new MssqlUser2(); + + $user->username='testingUser'; + $user->password='testingPassword'; + $user->email='testing@email.com'; + + $this->assertTrue($user->isNewRecord); + $this->assertNull($user->primaryKey); + $this->assertNull($user->id); + $this->assertEquals(3, $this->db->createCommand('SELECT MAX(id) FROM [dbo].[users]')->queryScalar()); + + $user->save(); + + $this->assertFalse($user->isNewRecord); + $this->assertEquals(4, $user->primaryKey); + $this->assertEquals(4, $user->id); + $this->assertEquals(4, $this->db->createCommand('SELECT MAX(id) FROM [dbo].[users]')->queryScalar()); + } + + public function testResetSequence() + { + $tables=$this->db->schema->tables; + + $this->db->schema->resetSequence($tables['users']); + $this->db->createCommand()->insert('users',array('username'=>'testerX','password'=>'passwordX','email'=>'emailX@gmail.com')); + $id=$this->db->createCommand()->select('id')->from('users')->where("[username]='testerX'")->queryScalar(); + $this->assertEquals(4,$id); + + $this->db->schema->resetSequence($tables['users'],100); + $this->db->createCommand()->insert('users',array('username'=>'testerY','password'=>'passwordY','email'=>'emailY@gmail.com')); + $id=$this->db->createCommand()->select('id')->from('users')->where("[username]='testerY'")->queryScalar(); + $this->assertEquals(100,$id); + + $this->db->schema->resetSequence($tables['users']); + $this->db->createCommand()->insert('users',array('username'=>'testerZ','password'=>'passwordZ','email'=>'emailZ@gmail.com')); + $id=$this->db->createCommand()->select('id')->from('users')->where("[username]='testerZ'")->queryScalar(); + $this->assertEquals(101,$id); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMysql2Test.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMysql2Test.php new file mode 100644 index 0000000..25b0d1c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMysql2Test.php @@ -0,0 +1,153 @@ +markTestSkipped('PDO and MySQL extensions are required.'); + + $this->db=new CDbConnection('mysql:host=127.0.0.1;dbname=yii','test','test'); + $this->db->charset='UTF8'; + try + { + $this->db->active=true; + } + catch(Exception $e) + { + $schemaFile=realpath(dirname(__FILE__).'/../data/mysql.sql'); + $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for MySQL test case."); + } + + $tables=array('comments','post_category','posts','categories','profiles','users','items','orders','types'); + foreach($tables as $table) + $this->db->createCommand("DROP TABLE IF EXISTS $table CASCADE")->execute(); + + $sqls=file_get_contents(dirname(__FILE__).'/../data/mysql.sql'); + foreach(explode(';',$sqls) as $sql) + { + if(trim($sql)!=='') + $this->db->createCommand($sql)->execute(); + } + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testCreateTable() + { + $sql=$this->db->schema->createTable('test',array( + 'id'=>'pk', + 'name'=>'string not null', + 'desc'=>'text', + 'primary key (id, name)', + ),'Engine=InnoDB'); + $expect="CREATE TABLE `test` (\n" + . "\t`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,\n" + . "\t`name` varchar(255) not null,\n" + . "\t`desc` text,\n" + . "\tprimary key (id, name)\n" + . ") Engine=InnoDB"; + $this->assertEquals($expect, $sql); + } + + public function testRenameTable() + { + $sql=$this->db->schema->renameTable('test', 'test2'); + $expect='RENAME TABLE `test` TO `test2`'; + $this->assertEquals($expect, $sql); + } + + public function testDropTable() + { + $sql=$this->db->schema->dropTable('test'); + $expect='DROP TABLE `test`'; + $this->assertEquals($expect, $sql); + } + + public function testAddColumn() + { + $sql=$this->db->schema->addColumn('test', 'id', 'integer'); + $expect='ALTER TABLE `test` ADD `id` int(11)'; + $this->assertEquals($expect, $sql); + } + + public function testAlterColumn() + { + $sql=$this->db->schema->alterColumn('test', 'id', 'boolean'); + $expect='ALTER TABLE `test` CHANGE `id` `id` tinyint(1)'; + $this->assertEquals($expect, $sql); + } + + public function testRenameColumn() + { + $sql=$this->db->schema->renameColumn('users', 'username', 'name'); + $expect="ALTER TABLE `users` CHANGE `username` `name` varchar(128) NOT NULL COMMENT 'Name of the user'"; + $this->assertEquals($expect, $sql); + } + + public function testDropColumn() + { + $sql=$this->db->schema->dropColumn('test', 'id'); + $expect='ALTER TABLE `test` DROP COLUMN `id`'; + $this->assertEquals($expect, $sql); + } + + public function testAddForeignKey() + { + $sql=$this->db->schema->addForeignKey('fk_test', 'profile', 'user_id', 'users', 'id'); + $expect='ALTER TABLE `profile` ADD CONSTRAINT `fk_test` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)'; + $this->assertEquals($expect, $sql); + + $sql=$this->db->schema->addForeignKey('fk_test', 'profile', 'user_id', 'users', 'id','CASCADE','RESTRICTED'); + $expect='ALTER TABLE `profile` ADD CONSTRAINT `fk_test` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE RESTRICTED'; + $this->assertEquals($expect, $sql); + } + + public function testDropForeignKey() + { + $sql=$this->db->schema->dropForeignKey('fk_test', 'profile'); + $expect='ALTER TABLE `profile` DROP FOREIGN KEY `fk_test`'; + $this->assertEquals($expect, $sql); + } + + public function testCreateIndex() + { + $sql=$this->db->schema->createIndex('id_pk','test','id'); + $expect='CREATE INDEX `id_pk` ON `test` (`id`)'; + $this->assertEquals($expect, $sql); + + $sql=$this->db->schema->createIndex('id_pk','test','id1,id2',true); + $expect='CREATE UNIQUE INDEX `id_pk` ON `test` (`id1`, `id2`)'; + $this->assertEquals($expect, $sql); + } + + public function testDropIndex() + { + $sql=$this->db->schema->dropIndex('id_pk','test'); + $expect='DROP INDEX `id_pk` ON `test`'; + $this->assertEquals($expect, $sql); + } + + public function testAddPrimaryKey() + { + $sql=$this->db->schema->addPrimaryKey('this-string-is-ignored','table','id'); + $expect='ALTER TABLE `table` ADD PRIMARY KEY (`id` )'; + $this->assertEquals($expect, $sql); + + $sql=$this->db->schema->addPrimaryKey('this-string-is-ignored','table',array('id1','id2')); + $expect='ALTER TABLE `table` ADD PRIMARY KEY (`id1`, `id2` )'; + $this->assertEquals($expect, $sql); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMysqlTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMysqlTest.php new file mode 100644 index 0000000..5829411 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CMysqlTest.php @@ -0,0 +1,317 @@ +markTestSkipped('PDO and MySQL extensions are required.'); + + $this->db=new CDbConnection('mysql:host=127.0.0.1;dbname=yii','test','test'); + $this->db->charset='UTF8'; + try + { + $this->db->active=true; + } + catch(Exception $e) + { + $schemaFile=realpath(dirname(__FILE__).'/../data/mysql.sql'); + $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for MySQL test case."); + } + + $tables=array('comments','post_category','posts','categories','profiles','users','items','orders','types'); + foreach($tables as $table) + $this->db->createCommand("DROP TABLE IF EXISTS $table CASCADE")->execute(); + + $sqls=file_get_contents(dirname(__FILE__).'/../data/mysql.sql'); + foreach(explode(';',$sqls) as $sql) + { + if(trim($sql)!=='') + $this->db->createCommand($sql)->execute(); + } + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testSchema() + { + $schema=$this->db->schema; + $this->assertTrue($schema instanceof CDbSchema); + $this->assertEquals($schema->dbConnection,$this->db); + $this->assertTrue($schema->commandBuilder instanceof CDbCommandBuilder); + $this->assertEquals('`posts`',$schema->quoteTableName('posts')); + $this->assertEquals('`id`',$schema->quoteColumnName('id')); + $this->assertTrue($schema->getTable('posts') instanceof CDbTableSchema); + $this->assertNull($schema->getTable('foo')); + } + + public function testTable() + { + $table=$this->db->schema->getTable('posts'); + $this->assertTrue($table instanceof CDbTableSchema); + $this->assertEquals('posts',$table->name); + $this->assertEquals('`posts`',$table->rawName); + $this->assertEquals('id',$table->primaryKey); + $this->assertEquals(array('author_id'=>array('users','id')),$table->foreignKeys); + $this->assertEquals('',$table->sequenceName); + $this->assertEquals(5,count($table->columns)); + + $this->assertTrue($table->getColumn('id') instanceof CDbColumnSchema); + $this->assertTrue($table->getColumn('foo')===null); + $this->assertEquals(array('id','title','create_time','author_id','content'),$table->columnNames); + + $table=$this->db->schema->getTable('orders'); + $this->assertEquals(array('key1','key2'),$table->primaryKey); + + $table=$this->db->schema->getTable('items'); + $this->assertEquals('id',$table->primaryKey); + $this->assertEquals(array('col1'=>array('orders','key1'),'col2'=>array('orders','key2')),$table->foreignKeys); + + $table=$this->db->schema->getTable('types'); + $this->assertTrue($table instanceof CDbTableSchema); + $this->assertEquals('types',$table->name); + $this->assertEquals('`types`',$table->rawName); + $this->assertTrue($table->primaryKey===null); + $this->assertTrue($table->foreignKeys===array()); + $this->assertTrue($table->sequenceName===null); + + $table=$this->db->schema->getTable('invalid'); + $this->assertNull($table); + } + + public function testColumn() + { + $values=array + ( + 'name'=>array('id', 'title', 'create_time', 'author_id', 'content'), + 'rawName'=>array('`id`', '`title`', '`create_time`', '`author_id`', '`content`'), + 'defaultValue'=>array(null, null, null, null, null), + 'size'=>array(11, 128, null, 11, null), + 'precision'=>array(11, 128, null, 11, null), + 'scale'=>array(null, null, null, null, null), + 'dbType'=>array('int(11)','varchar(128)','timestamp','int(11)','text'), + 'type'=>array('integer','string','string','integer','string'), + 'isPrimaryKey'=>array(true,false,false,false,false), + 'isForeignKey'=>array(false,false,false,true,false), + ); + $this->checkColumns('posts',$values); + $values=array + ( + 'name'=>array('int_col', 'int_col2', 'char_col', 'char_col2', 'char_col3', 'float_col', 'float_col2', 'blob_col', 'numeric_col', 'time', 'bool_col', 'bool_col2', 'bit_col1', 'bit_col2'), + 'rawName'=>array('`int_col`', '`int_col2`', '`char_col`', '`char_col2`', '`char_col3`', '`float_col`', '`float_col2`', '`blob_col`', '`numeric_col`', '`time`', '`bool_col`', '`bool_col2`', '`bit_col1`', '`bit_col2`'), + 'defaultValue'=>array(null, 1, null, 'something', null, null, '1.23', null, '33.22', '2002-01-01 00:00:00', null, 1, null, 42), + 'size'=>array(11, 11, 100, 100, null, 4, null, null, 5, null, 1, 1, 1, 32), + 'precision'=>array(11, 11, 100, 100, null, 4, null, null, 5, null, 1, 1, 1, 32), + 'scale'=>array(null, null, null, null, null, 3, null, null, 2, null, null, null, null, null), + 'dbType'=>array('int(11)','int(11)','char(100)','varchar(100)','text','double(4,3)','double','blob','decimal(5,2)','timestamp','tinyint(1)','tinyint(1)','bit(1)','bit(32)'), + 'type'=>array('integer','integer','string','string','string','double','double','string','string','string','integer','integer','integer','integer'), + 'isPrimaryKey'=>array(false,false,false,false,false,false,false,false,false,false,false,false,false,false), + 'isForeignKey'=>array(false,false,false,false,false,false,false,false,false,false,false,false,false,false), + ); + $this->checkColumns('types',$values); + } + + protected function checkColumns($tableName,$values) + { + $table=$this->db->schema->getTable($tableName); + foreach($values as $name=>$value) + { + foreach(array_values($table->columns) as $i=>$column) + { + $type1=gettype($column->$name); + $type2=gettype($value[$i]); + $this->assertTrue($column->$name===$value[$i], "$tableName.{$column->name}.$name is {$column->$name} ($type1), different from the expected {$value[$i]} ($type2)."); + } + } + } + + public function testCommandBuilder() + { + $schema=$this->db->schema; + $builder=$schema->commandBuilder; + $this->assertTrue($builder instanceof CDbCommandBuilder); + $table=$schema->getTable('posts'); + + $c=$builder->createInsertCommand($table,array('title'=>'test post','create_time'=>'2000-01-01','author_id'=>1,'content'=>'test content')); + $this->assertEquals('INSERT INTO `posts` (`title`, `create_time`, `author_id`, `content`) VALUES (:yp0, :yp1, :yp2, :yp3)',$c->text); + $c->execute(); + $this->assertEquals(6,$builder->getLastInsertId($table)); + + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals('SELECT COUNT(*) FROM `posts` `t`',$c->text); + $this->assertEquals(6,$c->queryScalar()); + + $c=$builder->createDeleteCommand($table,new CDbCriteria(array( + 'condition'=>'id=:id', + 'params'=>array('id'=>6)))); + $this->assertEquals('DELETE FROM `posts` WHERE id=:id',$c->text); + $c->execute(); + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals(5,$c->queryScalar()); + + // test for delete with joins + $c=$builder->createInsertCommand($table,array('title'=>'new post delete','create_time'=>'2000-01-01','author_id'=>1,'content'=>'test content')); + $c->execute(); + $c=$builder->createDeleteCommand($table,new CDbCriteria(array( + 'condition'=>'u.`username`=:username and `posts`.`title`=:title', + 'join'=>'JOIN `users` u ON `author_id`=u.`id`', + 'params'=>array(':username'=>'user1', ':title'=>'new post delete')))); + $this->assertEquals('DELETE `posts` FROM `posts` JOIN `users` u ON `author_id`=u.`id` WHERE u.`username`=:username and `posts`.`title`=:title',$c->text); + $c->execute(); + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals(5,$c->queryScalar()); + + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'id, title', + 'condition'=>'id=:id', + 'params'=>array('id'=>5), + 'order'=>'title', + 'limit'=>2, + 'offset'=>0))); + $this->assertEquals('SELECT id, title FROM `posts` `t` WHERE id=:id ORDER BY title LIMIT 2',$c->text); + $rows=$c->query()->readAll(); + $this->assertEquals(1,count($rows)); + $this->assertEquals('post 5',$rows[0]['title']); + + $c=$builder->createUpdateCommand($table,array('title'=>'new post 5'),new CDbCriteria(array( + 'condition'=>'id=:id', + 'params'=>array('id'=>5)))); + $c->execute(); + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=:id', + 'params'=>array('id'=>5)))); + $this->assertEquals('new post 5',$c->queryScalar()); + + $c=$builder->createSqlCommand('SELECT title FROM posts WHERE id=:id',array(':id'=>3)); + $this->assertEquals('post 3',$c->queryScalar()); + + $c=$builder->createUpdateCounterCommand($table,array('author_id'=>-1),new CDbCriteria(array('condition'=>'id=5'))); + $this->assertEquals('UPDATE `posts` SET `author_id`=`author_id`-1 WHERE id=5',$c->text); + $c->execute(); + $c=$builder->createSqlCommand('SELECT author_id FROM posts WHERE id=5'); + $this->assertEquals(2,$c->queryScalar()); + + // test for updates with joins + $c=$builder->createUpdateCommand($table,array('title'=>'new post 1'),new CDbCriteria(array( + 'condition'=>'u.`username`=:username', + 'join'=>'JOIN `users` u ON `author_id`=u.`id`', + 'params'=>array(':username'=>'user1')))); + $c->execute(); + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=:id', + 'params'=>array('id'=>1)))); + $this->assertEquals('new post 1',$c->queryScalar()); + + $c=$builder->createUpdateCounterCommand($table,array('author_id'=>-1),new CDbCriteria(array( + 'condition'=>'u.`username`="user2"', + 'join'=>'JOIN `users` u ON `author_id`=u.`id`'))); + $this->assertEquals('UPDATE `posts` JOIN `users` u ON `author_id`=u.`id` SET `author_id`=`author_id`-1 WHERE u.`username`="user2"',$c->text); + $c->execute(); + $c=$builder->createSqlCommand('SELECT author_id FROM posts WHERE id=2'); + $this->assertEquals(1,$c->queryScalar()); + + // test bind by position + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=?', + 'params'=>array(4)))); + $this->assertEquals('SELECT title FROM `posts` `t` WHERE id=?',$c->text); + $this->assertEquals('post 4',$c->queryScalar()); + + // another bind by position + $c=$builder->createUpdateCommand($table,array('title'=>'new post 4'),new CDbCriteria(array( + 'condition'=>'id=?', + 'params'=>array(4)))); + $c->execute(); + $c=$builder->createSqlCommand('SELECT title FROM posts WHERE id=4'); + $this->assertEquals('new post 4',$c->queryScalar()); + + // testCreateCriteria + $c=$builder->createCriteria('column=:value',array(':value'=>'value')); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c=$builder->createCriteria(array('condition'=>'column=:value','params'=>array(':value'=>'value'))); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c2=$builder->createCriteria($c); + $this->assertTrue($c2!==$c); + $this->assertEquals('column=:value',$c2->condition); + $this->assertEquals(array(':value'=>'value'),$c2->params); + + // testCreatePkCriteria + $c=$builder->createPkCriteria($table,1,'author_id>1'); + $this->assertEquals('`posts`.`id`=1 AND (author_id>1)',$c->condition); + + $c=$builder->createPkCriteria($table,array(1,2)); + $this->assertEquals('`posts`.`id` IN (1, 2)',$c->condition); + + $c=$builder->createPkCriteria($table,array()); + $this->assertEquals('0=1',$c->condition); + + $table2=$schema->getTable('orders'); + $c=$builder->createPkCriteria($table2,array('key1'=>1,'key2'=>2),'name=``'); + $this->assertEquals('`orders`.`key1`=1 AND `orders`.`key2`=2 AND (name=``)',$c->condition); + + $c=$builder->createPkCriteria($table2,array(array('key1'=>1,'key2'=>2),array('key1'=>3,'key2'=>4))); + $this->assertEquals('(`orders`.`key1`, `orders`.`key2`) IN ((1, 2), (3, 4))',$c->condition); + + // createColumnCriteria + $c=$builder->createColumnCriteria($table,array('id'=>1,'author_id'=>2),'title=``'); + $this->assertEquals('`posts`.`id`=:yp0 AND `posts`.`author_id`=:yp1 AND (title=``)',$c->condition); + + $c=$builder->createPkCriteria($table2,array()); + $this->assertEquals('0=1',$c->condition); + } + + public function testResetSequence() + { + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->db->createCommand("DELETE FROM users")->execute(); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max2=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals($max+1,$max2); + + $userTable=$this->db->schema->getTable('users'); + + $this->db->createCommand("DELETE FROM users")->execute(); + $this->db->schema->resetSequence($userTable);return; + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals(1,$max); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals(2,$max); + + $this->db->createCommand("DELETE FROM users")->execute(); + $this->db->schema->resetSequence($userTable,10); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals(10,$max); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals(11,$max); + } + + public function testColumnComments() + { + $usersColumns=$this->db->schema->tables['users']->columns; + + $this->assertEquals('',$usersColumns['id']->comment); + $this->assertEquals('Name of the user',$usersColumns['username']->comment); + $this->assertEquals('Hashed password',$usersColumns['password']->comment); + $this->assertEquals('',$usersColumns['email']->comment); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/COciTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/COciTest.php new file mode 100644 index 0000000..deb4c7b --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/COciTest.php @@ -0,0 +1,378 @@ +markTestSkipped('PDO and OCI extensions are required.'); + + $dsn=self::DB_DSN_PREFIX.':dbname='.self::DB_HOST.':'.self::DB_PORT.'/'.self::DB_SERVICE.';charset=UTF8'; + $schemaFilePath=realpath(dirname(__FILE__).'/../data/oci.sql'); + + $this->db=new CDbConnection($dsn, self::DB_USER, self::DB_PASS); + $this->db->charset='UTF8'; + + try + { + $this->db->active=true; + } + catch(Exception $e) + { + echo $e->getMessage(); + $this->markTestSkipped("Please read {$schemaFilePath} for details on setting up the test environment for OCI test case."); + } + + $tables=array('comments', 'post_category', 'posts', 'categories', 'profiles', 'users', 'items', 'orders', 'types'); + + // delete existing sequences + foreach($tables as $table) + { + if($table==='post_category' || $table==='orders' || $table==='types') + continue; + $sequence=$table.'_id_sequence'; + $sql=<<db->createCommand($sql)->execute(); + } + + // delete existing tables + foreach($tables as $table) + { + $sql=<<db->createCommand($sql)->execute(); + } + + $sqls=''; + foreach(explode("\n", file_get_contents($schemaFilePath)) as $line) + { + if(substr($line, 0, 2)==='--') + continue; + $sqls.=$line."\n"; + } + foreach(array_filter(explode("\n\n", $sqls)) as $sql) + { + if(trim($sql)!=='') + { + if(mb_substr($sql, -4)!=='END;') // do not remove semicolons after BEGIN END blocks + $sql=rtrim($sql, ';'); + $this->db->createCommand($sql)->execute(); + } + } + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testSchema() + { + $schema=$this->db->schema; + $this->assertInstanceOf('CDbSchema', $schema); + $this->assertEquals($schema->dbConnection, $this->db); + $this->assertInstanceOf('CDbCommandBuilder', $schema->commandBuilder); + $this->assertEquals('"users"', $schema->quoteTableName('users')); + $this->assertEquals('"id"', $schema->quoteColumnName('id')); + $this->assertInstanceOf('CDbTableSchema', $schema->getTable('users')); + $this->assertNull($schema->getTable('foo')); + } + + public function testTable() + { + $table=$this->db->schema->getTable('posts'); + $this->assertInstanceOf('CDbTableSchema', $table); + $this->assertEquals('posts', $table->name); + $this->assertEquals('"posts"', $table->rawName); + $this->assertEquals('id', $table->primaryKey); + $this->assertEquals(array('author_id'=>array('users', 'id')), $table->foreignKeys); + $this->assertEmpty($table->sequenceName); + $this->assertCount(5, $table->columns); + + $this->assertInstanceOf('CDbColumnSchema', $table->getColumn('id')); + $this->assertNull($table->getColumn('foo')); + $this->assertEquals(array('id', 'title', 'create_time', 'author_id', 'content'), $table->columnNames); + + $table=$this->db->schema->getTable('orders'); + $this->assertEquals(array('key1', 'key2'), $table->primaryKey); + + $table=$this->db->schema->getTable('items'); + $this->assertEquals('id', $table->primaryKey); + $this->assertEquals(array('col1'=>array('orders', 'key1'), 'col2'=>array('orders', 'key2')), $table->foreignKeys); + + $table=$this->db->schema->getTable('types'); + $this->assertInstanceOf('CDbTableSchema', $table); + $this->assertEquals('types', $table->name); + $this->assertEquals('"types"', $table->rawName); + $this->assertNull($table->primaryKey); + $this->assertEmpty($table->foreignKeys); + $this->assertNull($table->sequenceName); + + $table=$this->db->schema->getTable('invalid'); + $this->assertNull($table); + } + + public function testColumn() + { + $values=array( + 'name'=>array('id', 'title', 'create_time', 'author_id', 'content'), + 'rawName'=>array('"id"', '"title"', '"create_time"', '"author_id"', '"content"'), + 'defaultValue'=>array(null, null, null, null, null), + 'size'=>array(null, 512, 6, null, 4000), + 'precision'=>array(null, 512, 6, null, 4000), + 'scale'=>array(null, null, null, null, null), + 'dbType'=>array('NUMBER','VARCHAR2(512)','TIMESTAMP(6)(11)','NUMBER','CLOB(4000)'), + 'type'=>array('double','string','string','double','string'), + 'isPrimaryKey'=>array(true,false,false,false,false), + 'isForeignKey'=>array(false,false,false,true,false), + ); + $this->checkColumns('posts',$values); + } + + protected function checkColumns($tableName,$values) + { + $table=$this->db->schema->getTable($tableName); + foreach($values as $name=>$value) + { + foreach(array_values($table->columns) as $i=>$column) + { + $type1=gettype($column->$name); + $type2=gettype($value[$i]); + $this->assertTrue($column->$name===$value[$i], "$tableName.{$column->name}.$name is {$column->$name} ($type1), different from the expected {$value[$i]} ($type2)."); + } + } + } + + public function testCommandBuilder() + { + $schema=$this->db->schema; + $builder=$schema->commandBuilder; + $this->assertTrue($builder instanceof CDbCommandBuilder); + $table=$schema->getTable('posts'); + + $c=$builder->createInsertCommand($table,array('title'=>'test post','create_time'=>new CDbExpression('TO_TIMESTAMP(:ts_value, \'YYYY-MM-DD\')', array(':ts_value'=>'2000-01-01')),'author_id'=>1,'content'=>'test content')); + $this->assertEquals('INSERT INTO "posts" ("title", "create_time", "author_id", "content") VALUES (:yp0, TO_TIMESTAMP(:ts_value, \'YYYY-MM-DD\'), :yp1, :yp2) RETURNING "id" INTO :RETURN_ID',$c->text); + $c->execute(); + $this->assertEquals(6,$builder->getLastInsertId($table)); + + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals('SELECT COUNT(*) FROM "posts" "t"',$c->text); + $this->assertEquals(6,$c->queryScalar()); + + $c=$builder->createDeleteCommand($table,new CDbCriteria(array( + 'condition'=>'"id"=:id', + 'params'=>array('id'=>6)))); + $this->assertEquals('DELETE FROM "posts" WHERE "id"=:id',$c->text); + $c->execute(); + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals(5,$c->queryScalar()); + + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'"id", "title"', + 'condition'=>'"id"=:id', + 'params'=>array(':id'=>5), + 'order'=>'"title"', + 'limit'=>2, + 'offset'=>0))); + $this->assertEquals('WITH USER_SQL AS (SELECT "id", "title" FROM "posts" "t" WHERE "id"=:id ORDER BY "title"), + PAGINATION AS (SELECT USER_SQL.*, rownum as rowNumId FROM USER_SQL) +SELECT * +FROM PAGINATION + WHERE rownum <= 2', $c->text); + $rows=$c->query()->readAll(); + $this->assertEquals(1,count($rows)); + $this->assertEquals('post 5',$rows[0]['title']); + + $c=$builder->createUpdateCommand($table,array('title'=>'new post 5'),new CDbCriteria(array( + 'condition'=>'"id"=:id', + 'params'=>array('id'=>5)))); + $c->execute(); + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'"title"', + 'condition'=>'"id"=:id', + 'params'=>array('id'=>5)))); + $this->assertEquals('new post 5',$c->queryScalar()); + + $c=$builder->createSqlCommand('SELECT "title" FROM "posts" WHERE "id"=:id',array(':id'=>3)); + $this->assertEquals('post 3',$c->queryScalar()); + + $c=$builder->createUpdateCounterCommand($table,array('author_id'=>-1),new CDbCriteria(array('condition'=>'"id"=5'))); + $this->assertEquals('UPDATE "posts" SET "author_id"="author_id"-1 WHERE "id"=5',$c->text); + $c->execute(); + $c=$builder->createSqlCommand('SELECT "author_id" FROM "posts" WHERE "id"=5'); + $this->assertEquals(2,$c->queryScalar()); + + // Oracle does not support UPDATE with JOINs so there are no tests of them + + // test bind by position + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'"title"', + 'condition'=>'"id"=?', + 'params'=>array(4)))); + $this->assertEquals('SELECT "title" FROM "posts" "t" WHERE "id"=?',$c->text); + $this->assertEquals('post 4',$c->queryScalar()); + + // another bind by position + $c=$builder->createUpdateCommand($table,array('title'=>'new post 4'),new CDbCriteria(array( + 'condition'=>'"id"=?', + 'params'=>array(4)))); + $c->execute(); + $c=$builder->createSqlCommand('SELECT "title" FROM "posts" WHERE "id"=4'); + $this->assertEquals('new post 4',$c->queryScalar()); + + // testCreateCriteria + $c=$builder->createCriteria('column=:value',array(':value'=>'value')); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c=$builder->createCriteria(array('condition'=>'column=:value','params'=>array(':value'=>'value'))); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c2=$builder->createCriteria($c); + $this->assertTrue($c2!==$c); + $this->assertEquals('column=:value',$c2->condition); + $this->assertEquals(array(':value'=>'value'),$c2->params); + + // testCreatePkCriteria + $c=$builder->createPkCriteria($table,1,'author_id>1'); + $this->assertEquals('"posts"."id"=1 AND (author_id>1)',$c->condition); + + $c=$builder->createPkCriteria($table,array(1,2)); + $this->assertEquals('"posts"."id" IN (1, 2)',$c->condition); + + $c=$builder->createPkCriteria($table,array()); + $this->assertEquals('0=1',$c->condition); + + $table2=$schema->getTable('orders'); + $c=$builder->createPkCriteria($table2,array('key1'=>1,'key2'=>2),'name=""'); + $this->assertEquals('"orders"."key1"=1 AND "orders"."key2"=2 AND (name="")',$c->condition); + + $c=$builder->createPkCriteria($table2,array(array('key1'=>1,'key2'=>2),array('key1'=>3,'key2'=>4))); + $this->assertEquals('("orders"."key1", "orders"."key2") IN ((1, 2), (3, 4))',$c->condition); + + // createColumnCriteria + $c=$builder->createColumnCriteria($table,array('id'=>1,'author_id'=>2),'title=""'); + $this->assertEquals('"posts"."id"=:yp0 AND "posts"."author_id"=:yp1 AND (title="")',$c->condition); + + $c=$builder->createPkCriteria($table2,array()); + $this->assertEquals('0=1',$c->condition); + } + + public function testResetSequence() + { + // we're assuming in this test that COciSchema::resetSequence() is not implemented + // empty CDbSchema::resetSequence() being used + + $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar(); + $this->db->createCommand('DELETE FROM "users"')->execute(); + $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute(); + $max2=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar(); + $this->assertEquals($max+1, $max2); + + $userTable=$this->db->schema->getTable('users'); + + $this->db->createCommand('DELETE FROM "users"')->execute(); + $this->db->schema->resetSequence($userTable); + $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute(); + $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar(); + $this->assertEquals(6, $max); + $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute(); + $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar(); + $this->assertEquals(7, $max); + + $this->db->createCommand('DELETE FROM "users"')->execute(); + $this->db->schema->resetSequence($userTable, 10); + $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute(); + $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar(); + $this->assertEquals(8, $max); + $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute(); + $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar(); + $this->assertEquals(9, $max); + } + + public function testColumnComments() + { + $tables=$this->db->schema->tables; + + // specified comments + $usersColumns=$tables['users']->columns; + $this->assertEquals('User\'s entry primary key', $usersColumns['id']->comment); + $this->assertEquals('Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ', $usersColumns['username']->comment); + $this->assertEquals('用户的密ç ', $usersColumns['password']->comment); + $this->assertEquals('דו×"ל של המשתמש', $usersColumns['email']->comment); + + // empty comments + $postsColumns=$tables['posts']->columns; + $this->assertEmpty($postsColumns['id']->comment); + $this->assertEmpty($postsColumns['title']->comment); + $this->assertEmpty($postsColumns['create_time']->comment); + $this->assertEmpty($postsColumns['author_id']->comment); + $this->assertEmpty($postsColumns['content']->comment); + } + + public function testMultipleInsert() + { + $builder=$this->db->getSchema()->getCommandBuilder(); + $tableName='types'; + $data=array( + array( + 'int_col'=>1, + 'char_col'=>'char_col_1', + 'char_col2'=>'char_col_2_1', + 'float_col'=>1, + 'bool_col'=>true, + ), + array( + 'int_col'=>2, + 'char_col'=>'char_col_2', + 'float_col'=>2, + 'bool_col'=>false, + ), + ); + $command=$builder->createMultipleInsertCommand($tableName,$data); + $command->execute(); + + $rows=$builder->dbConnection->createCommand('SELECT * FROM '.$builder->dbConnection->quoteTableName($tableName))->queryAll(); + + $this->assertEquals(count($data),count($rows),'Records count miss matches!'); + foreach($rows as $rowIndex=>$row) + foreach($row as $columnName=>$value) + { + $columnIndex=array_search($columnName,$data[$rowIndex],true); + if($columnIndex==false) + continue; + $expectedValue=$data[$rowIndex][$columnIndex]; + $this->assertTrue($expectedValue==$value,"Value for column '{$columnName}' incorrect!"); + } + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CPostgres2Test.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CPostgres2Test.php new file mode 100644 index 0000000..e4cbcce --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CPostgres2Test.php @@ -0,0 +1,126 @@ +markTestSkipped('PDO and PostgreSQL extensions are required.'); + + $this->db=new CDbConnection('pgsql:host=127.0.0.1;dbname=yii','test','test'); + $this->db->charset='UTF8'; + try + { + $this->db->active=true; + } + catch(Exception $e) + { + $schemaFile=realpath(dirname(__FILE__).'/../data/postgres.sql'); + $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for PostgreSQL test case."); + } + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testCreateTable() + { + $sql=$this->db->schema->createTable('test',array( + 'id'=>'pk', + 'name'=>'string not null', + 'desc'=>'text', + 'primary key (id, name)', + )); + $expect="CREATE TABLE \"test\" (\n" + . "\t\"id\" serial NOT NULL PRIMARY KEY,\n" + . "\t\"name\" character varying (255) not null,\n" + . "\t\"desc\" text,\n" + . "\tprimary key (id, name)\n" + . ")"; + $this->assertEquals($expect, $sql); + } + + public function testRenameTable() + { + $sql=$this->db->schema->renameTable('test', 'test2'); + $expect='ALTER TABLE "test" RENAME TO "test2"'; + $this->assertEquals($expect, $sql); + } + + public function testDropTable() + { + $sql=$this->db->schema->dropTable('test'); + $expect='DROP TABLE "test"'; + $this->assertEquals($expect, $sql); + } + + public function testAddColumn() + { + $sql=$this->db->schema->addColumn('test', 'id', 'integer'); + $expect='ALTER TABLE "test" ADD COLUMN "id" integer'; + $this->assertEquals($expect, $sql); + } + + public function testAlterColumn() + { + $sql=$this->db->schema->alterColumn('test', 'id', 'boolean'); + $expect='ALTER TABLE "test" ALTER COLUMN "id" TYPE boolean'; + $this->assertEquals($expect, $sql); + } + + public function testRenameColumn() + { + $sql=$this->db->schema->renameColumn('users', 'username', 'name'); + $expect='ALTER TABLE "users" RENAME COLUMN "username" TO "name"'; + $this->assertEquals($expect, $sql); + } + + public function testDropColumn() + { + $sql=$this->db->schema->dropColumn('test', 'id'); + $expect='ALTER TABLE "test" DROP COLUMN "id"'; + $this->assertEquals($expect, $sql); + } + + public function testAddForeignKey() + { + $sql=$this->db->schema->addForeignKey('fk_test', 'profile', 'user_id', 'users', 'id'); + $expect='ALTER TABLE "profile" ADD CONSTRAINT "fk_test" FOREIGN KEY ("user_id") REFERENCES "users" ("id")'; + $this->assertEquals($expect, $sql); + + $sql=$this->db->schema->addForeignKey('fk_test', 'profile', 'user_id', 'users', 'id','CASCADE','RESTRICTED'); + $expect='ALTER TABLE "profile" ADD CONSTRAINT "fk_test" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE RESTRICTED'; + $this->assertEquals($expect, $sql); + } + + public function testDropForeignKey() + { + $sql=$this->db->schema->dropForeignKey('fk_test', 'profile'); + $expect='ALTER TABLE "profile" DROP CONSTRAINT "fk_test"'; + $this->assertEquals($expect, $sql); + } + + public function testCreateIndex() + { + $sql=$this->db->schema->createIndex('id_pk','test','id'); + $expect='CREATE INDEX "id_pk" ON "test" ("id")'; + $this->assertEquals($expect, $sql); + + $sql=$this->db->schema->createIndex('id_pk','test','id1,id2',true); + $expect='CREATE UNIQUE INDEX "id_pk" ON "test" ("id1", "id2")'; + $this->assertEquals($expect, $sql); + } + + public function testDropIndex() + { + $sql=$this->db->schema->dropIndex('id_pk','test'); + $expect='DROP INDEX "id_pk"'; + $this->assertEquals($expect, $sql); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CPostgresTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CPostgresTest.php new file mode 100644 index 0000000..2bb9387 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CPostgresTest.php @@ -0,0 +1,274 @@ +markTestSkipped('PDO and PostgreSQL extensions are required.'); + + $this->db=new CDbConnection('pgsql:host=127.0.0.1;dbname=yii','test','test'); + $this->db->charset='UTF8'; + try + { + $this->db->active=true; + } + catch(Exception $e) + { + $schemaFile=realpath(dirname(__FILE__).'/../data/postgres.sql'); + $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for PostgreSQL test case."); + } + + try { $this->db->createCommand('DROP SCHEMA test CASCADE')->execute(); } catch(Exception $e) { } + try { $this->db->createCommand('DROP TABLE yii_types CASCADE')->execute(); } catch(Exception $e) { } + + $sqls=file_get_contents(dirname(__FILE__).'/../data/postgres.sql'); + foreach(explode(';',$sqls) as $sql) + { + if(trim($sql)!=='') + $this->db->createCommand($sql)->execute(); + } + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testSchema() + { + $schema=$this->db->schema; + $this->assertTrue($schema instanceof CDbSchema); + $this->assertEquals($schema->dbConnection,$this->db); + $this->assertTrue($schema->commandBuilder instanceof CDbCommandBuilder); + $this->assertEquals('"posts"',$schema->quoteTableName('posts')); + $this->assertEquals('"id"',$schema->quoteColumnName('id')); + $this->assertTrue($schema->getTable('test.posts') instanceof CDbTableSchema); + $this->assertTrue($schema->getTable('foo')===null); + } + + public function testTable() + { + $table=$this->db->schema->getTable('test.posts'); + $this->assertTrue($table instanceof CDbTableSchema); + $this->assertEquals('posts',$table->name); + $this->assertEquals('"test"."posts"',$table->rawName); + $this->assertEquals('id',$table->primaryKey); + $this->assertEquals(array('author_id'=>array('users','id')),$table->foreignKeys); + $this->assertEquals('test.posts_id_seq',$table->sequenceName); + $this->assertEquals(5,count($table->columns)); + + $this->assertTrue($table->getColumn('id') instanceof CDbColumnSchema); + $this->assertTrue($table->getColumn('foo')===null); + $this->assertEquals(array('id','title','create_time','author_id','content'),$table->columnNames); + + $table=$this->db->schema->getTable('test.orders'); + $this->assertEquals(array('key1','key2'),$table->primaryKey); + + $table=$this->db->schema->getTable('test.items'); + $this->assertEquals('id',$table->primaryKey); + $this->assertEquals(array('col1'=>array('orders','key1'),'col2'=>array('orders','key2')),$table->foreignKeys); + + $table=$this->db->schema->getTable('yii_types'); + $this->assertTrue($table instanceof CDbTableSchema); + $this->assertEquals('yii_types',$table->name); + $this->assertEquals('"yii_types"',$table->rawName); + $this->assertTrue($table->primaryKey===null); + $this->assertTrue($table->foreignKeys===array()); + $this->assertTrue($table->sequenceName===null); + + $table=$this->db->schema->getTable('invalid'); + $this->assertNull($table); + } + + public function testColumn() + { + $values=array + ( + 'name'=>array('id', 'title', 'create_time', 'author_id', 'content'), + 'rawName'=>array('"id"', '"title"', '"create_time"', '"author_id"', '"content"'), + 'defaultValue'=>array(null, null, null, null, null), + 'size'=>array(null, 128, null, null, null), + 'precision'=>array(null, 128, null, null, null), + 'scale'=>array(null, null, null, null, null), + 'type'=>array('integer','string','string','integer','string'), + 'isPrimaryKey'=>array(true,false,false,false,false), + 'isForeignKey'=>array(false,false,false,true,false), + ); + $this->checkColumns('test.posts',$values); + $values=array + ( + 'name'=>array('int_col', 'int_col2', 'char_col', 'char_col2', 'char_col3', 'numeric_col', 'real_col', 'blob_col', 'time', 'bool_col', 'bool_col2'), + 'rawName'=>array('"int_col"', '"int_col2"', '"char_col"', '"char_col2"', '"char_col3"', '"numeric_col"', '"real_col"', '"blob_col"', '"time"', '"bool_col"', '"bool_col2"'), + 'defaultValue'=>array(null, 1, null, 'something', null, null, '1.23', null, null, null, true), + 'size'=>array(null, null, 100, 100, null, 4, null, null, null, null, null), + 'precision'=>array(null, null, 100, 100, null, 4, null, null, null, null, null), + 'scale'=>array(null, null, null, null, null, 3, null, null, null, null, null), + 'type'=>array('integer','integer','string','string','string','string','double','string','string','boolean','boolean'), + 'isPrimaryKey'=>array(false,false,false,false,false,false,false,false,false,false,false), + 'isForeignKey'=>array(false,false,false,false,false,false,false,false,false,false,false), + ); + $this->checkColumns('yii_types',$values); + } + + protected function checkColumns($tableName,$values) + { + $table=$this->db->schema->getTable($tableName); + foreach($values as $name=>$value) + { + foreach(array_values($table->columns) as $i=>$column) + { + $type1=gettype($column->$name); + $type2=gettype($value[$i]); + $this->assertTrue($column->$name===$value[$i], "$tableName.{$column->name}.$name is {$column->$name} ($type1), different from the expected {$value[$i]} ($type2)."); + } + } + } + + public function testCommandBuilder() + { + $schema=$this->db->schema; + $builder=$schema->commandBuilder; + $this->assertTrue($builder instanceof CDbCommandBuilder); + $table=$schema->getTable('test.posts'); + + $c=$builder->createInsertCommand($table,array('title'=>'test post','create_time'=>'2004-10-19 10:23:54','author_id'=>1,'content'=>'test content')); + $this->assertEquals('INSERT INTO "test"."posts" ("title", "create_time", "author_id", "content") VALUES (:yp0, :yp1, :yp2, :yp3)',$c->text); + $c->execute(); + $this->assertEquals(6,$builder->getLastInsertId($table)); + + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals('SELECT COUNT(*) FROM "test"."posts" "t"',$c->text); + $this->assertEquals(6,$c->queryScalar()); + + $c=$builder->createDeleteCommand($table,new CDbCriteria(array( + 'condition'=>'id=:id', + 'params'=>array('id'=>6)))); + $this->assertEquals('DELETE FROM "test"."posts" WHERE id=:id',$c->text); + $c->execute(); + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals(5,$c->queryScalar()); + + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'id, title', + 'condition'=>'id=:id', + 'params'=>array('id'=>5), + 'order'=>'title', + 'limit'=>2, + 'offset'=>0))); + $this->assertEquals('SELECT id, title FROM "test"."posts" "t" WHERE id=:id ORDER BY title LIMIT 2',$c->text); + $rows=$c->query()->readAll(); + $this->assertEquals(1,count($rows)); + $this->assertEquals('post 5',$rows[0]['title']); + + $c=$builder->createUpdateCommand($table,array('title'=>'new post 5'),new CDbCriteria(array( + 'condition'=>'id=:id', + 'params'=>array('id'=>5)))); + $c->execute(); + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=:id', + 'params'=>array('id'=>5)))); + $this->assertEquals('new post 5',$c->queryScalar()); + + $c=$builder->createSqlCommand('SELECT title FROM test.posts WHERE id=:id',array(':id'=>3)); + $this->assertEquals('post 3',$c->queryScalar()); + + $c=$builder->createUpdateCounterCommand($table,array('author_id'=>-2),new CDbCriteria(array('condition'=>'id=5'))); + $this->assertEquals('UPDATE "test"."posts" SET "author_id"="author_id"-2 WHERE id=5',$c->text); + $c->execute(); + $c=$builder->createSqlCommand('SELECT author_id FROM posts WHERE id=5'); + $this->assertEquals(1,$c->queryScalar()); + + // test bind by position + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=?', + 'params'=>array(4)))); + $this->assertEquals('SELECT title FROM "test"."posts" "t" WHERE id=?',$c->text); + $this->assertEquals('post 4',$c->queryScalar()); + + // another bind by position + $c=$builder->createUpdateCommand($table,array('title'=>'new post 4'),new CDbCriteria(array( + 'condition'=>'id=?', + 'params'=>array(4)))); + $c->execute(); + $c=$builder->createSqlCommand('SELECT title FROM test.posts WHERE id=4'); + $this->assertEquals('new post 4',$c->queryScalar()); + + // testCreateCriteria + $c=$builder->createCriteria('column=:value',array(':value'=>'value')); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c=$builder->createCriteria(array('condition'=>'column=:value','params'=>array(':value'=>'value'))); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c2=$builder->createCriteria($c); + $this->assertTrue($c2!==$c); + $this->assertEquals('column=:value',$c2->condition); + $this->assertEquals(array(':value'=>'value'),$c2->params); + + // testCreatePkCriteria + $c=$builder->createPkCriteria($table,1,'author_id>1'); + $this->assertEquals('"test"."posts"."id"=1 AND (author_id>1)',$c->condition); + + $c=$builder->createPkCriteria($table,array(1,2)); + $this->assertEquals('"test"."posts"."id" IN (1, 2)',$c->condition); + + $table2=$schema->getTable('test.orders'); + $c=$builder->createPkCriteria($table2,array('key1'=>1,'key2'=>2),'name=\'\''); + $this->assertEquals('"test"."orders"."key1"=1 AND "test"."orders"."key2"=2 AND (name=\'\')',$c->condition); + + $c=$builder->createPkCriteria($table2,array(array('key1'=>1,'key2'=>2),array('key1'=>3,'key2'=>4))); + $this->assertEquals('("test"."orders"."key1", "test"."orders"."key2") IN ((1, 2), (3, 4))',$c->condition); + + // createColumnCriteria + $c=$builder->createColumnCriteria($table,array('id'=>1,'author_id'=>2),'title=\'\''); + $this->assertEquals('"test"."posts"."id"=:yp0 AND "test"."posts"."author_id"=:yp1 AND (title=\'\')',$c->condition); + } + + public function testResetSequence() + { + $max=$this->db->createCommand("SELECT MAX(id) FROM test.users")->queryScalar(); + $this->db->createCommand("DELETE FROM test.users")->execute(); + $this->db->createCommand("INSERT INTO test.users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max2=$this->db->createCommand("SELECT MAX(id) FROM test.users")->queryScalar(); + $this->assertEquals($max+1,$max2); + + $userTable=$this->db->schema->getTable('test.users'); + + $this->db->createCommand("DELETE FROM test.users")->execute(); + $this->db->schema->resetSequence($userTable); + $this->db->createCommand("INSERT INTO test.users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM test.users")->queryScalar(); + $this->assertEquals(1,$max); + $this->db->createCommand("INSERT INTO test.users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM test.users")->queryScalar(); + $this->assertEquals(2,$max); + + $this->db->createCommand("DELETE FROM test.users")->execute(); + $this->db->schema->resetSequence($userTable,10); + $this->db->createCommand("INSERT INTO test.users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM test.users")->queryScalar(); + $this->assertEquals(10,$max); + $this->db->createCommand("INSERT INTO test.users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM test.users")->queryScalar(); + $this->assertEquals(11,$max); + } + + public function testColumnComments() + { + $usersColumns=$this->db->schema->getTable('test.users')->columns; + + $this->assertEquals('',$usersColumns['id']->comment); + $this->assertEquals('Name of the user',$usersColumns['username']->comment); + $this->assertEquals('Hashed password',$usersColumns['password']->comment); + $this->assertEquals('',$usersColumns['email']->comment); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CSqliteTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CSqliteTest.php new file mode 100644 index 0000000..ef6949c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/db/schema/CSqliteTest.php @@ -0,0 +1,336 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->db=new CDbConnection('sqlite::memory:'); + $this->db->active=true; + $this->db->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/../data/sqlite.sql')); + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testSchema() + { + $schema=$this->db->schema; + $this->assertTrue($schema instanceof CDbSchema); + $this->assertEquals($schema->dbConnection,$this->db); + $this->assertTrue($schema->commandBuilder instanceof CDbCommandBuilder); + $this->assertEquals('\'posts\'',$schema->quoteTableName('posts')); + $this->assertEquals('"id"',$schema->quoteColumnName('id')); + $this->assertTrue($schema->getTable('posts') instanceof CDbTableSchema); + $this->assertTrue($schema->getTable('foo')===null); + } + + public function testTable() + { + $table=$this->db->schema->getTable('posts'); + $this->assertTrue($table instanceof CDbTableSchema); + $this->assertEquals('posts',$table->name); + $this->assertEquals('\'posts\'',$table->rawName); + $this->assertEquals('id',$table->primaryKey); + $this->assertEquals(array('author_id'=>array('users','id')),$table->foreignKeys); + $this->assertTrue($table->sequenceName===''); + $this->assertEquals(5,count($table->columns)); + + $this->assertTrue($table->getColumn('id') instanceof CDbColumnSchema); + $this->assertTrue($table->getColumn('foo')===null); + $this->assertEquals(array('id','title','create_time','author_id','content'),$table->columnNames); + + $table=$this->db->schema->getTable('orders'); + $this->assertEquals(array('key1','key2'),$table->primaryKey); + + $table=$this->db->schema->getTable('items'); + $this->assertEquals('id',$table->primaryKey); + $this->assertEquals(array('col1'=>array('orders','key1'),'col2'=>array('orders','key2')),$table->foreignKeys); + + $table=$this->db->schema->getTable('types'); + $this->assertTrue($table->primaryKey===null); + $this->assertTrue($table->foreignKeys===array()); + $this->assertTrue($table->sequenceName===null); + + $table=$this->db->schema->getTable('invalid'); + $this->assertNull($table); + } + + public function testColumn() + { + $values=array + ( + 'name'=>array('id', 'title', 'create_time', 'author_id', 'content'), + 'rawName'=>array('"id"', '"title"', '"create_time"', '"author_id"', '"content"'), + 'defaultValue'=>array(null, null, null, null, null), + 'size'=>array(null, 128, null, null, null), + 'precision'=>array(null, 128, null, null, null), + 'scale'=>array(null, null, null, null, null), + 'dbType'=>array('integer','varchar(128)','timestamp','integer','text'), + 'type'=>array('integer','string','string','integer','string'), + 'isPrimaryKey'=>array(true,false,false,false,false), + 'isForeignKey'=>array(false,false,false,true,false), + 'allowNull'=>array(false,false,false,false,true), + ); + $this->checkColumns('posts',$values); + $values=array + ( + 'name'=>array('int_col', 'int_col2', 'char_col', 'char_col2', 'char_col3', 'char_col4', 'char_col5', 'float_col', 'float_col2', 'blob_col', 'numeric_col', 'time', 'bool_col', 'bool_col2', 'null_col', 'created_at'), + 'rawName'=>array('"int_col"', '"int_col2"', '"char_col"', '"char_col2"', '"char_col3"', '"char_col4"', '"char_col5"', '"float_col"', '"float_col2"', '"blob_col"', '"numeric_col"', '"time"', '"bool_col"', '"bool_col2"', '"null_col"', '"created_at"'), + 'defaultValue'=>array(null, 1, null, 'something', null, null, 'NULL', null, '1.23', null, '33.22', '123', null, true, null, null), + 'size'=>array(null, null, 100, 100, null, 100, 100, 4, null, null, 5, null, null, null, null, null), + 'precision'=>array(null, null, 100, 100, null, 100, 100, 4, null, null, 5, null, null, null, null, null), + 'scale'=>array(null, null, null, null, null, null, null, 3, null, null, 2, null, null, null, null, null), + 'dbType'=>array('int','integer','char(100)','varchar(100)','text','varchar(100)','varchar(100)','real(4,3)','double','blob','numeric(5,2)','timestamp','bool','boolean','integer','timestamp'), + 'type'=>array('integer','integer','string','string','string','string','string','double','double','string','string','string','boolean','boolean','integer','string'), + 'isPrimaryKey'=>array(false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false), + 'isForeignKey'=>array(false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false), + 'allowNull'=>array(false,true,false,true,true,true,true,false,true,true,true,true,false,true,true,false), + ); + $this->checkColumns('types',$values); + } + + protected function checkColumns($tableName,$values) + { + $table=$this->db->schema->getTable($tableName); + foreach($values as $name=>$value) + { + foreach(array_values($table->columns) as $i=>$column) + { + $type1=gettype($column->$name); + $type2=gettype($value[$i]); + $this->assertTrue($column->$name===$value[$i], "$tableName.{$column->name}.$name is {$column->$name} ($type1), different from the expected {$value[$i]} ($type2)."); + } + } + } + + public function testCommandBuilder() + { + $schema=$this->db->schema; + $builder=$schema->commandBuilder; + $this->assertTrue($builder instanceof CDbCommandBuilder); + $table=$schema->getTable('posts'); + + $c=$builder->createInsertCommand($table,array('title'=>'test post','create_time'=>time(),'author_id'=>1,'content'=>'test content')); + $this->assertEquals('INSERT INTO \'posts\' ("title", "create_time", "author_id", "content") VALUES (:yp0, :yp1, :yp2, :yp3)',$c->text); + $c->execute(); + $this->assertEquals(6,$builder->getLastInsertId($table)); + + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals('SELECT COUNT(*) FROM \'posts\' \'t\'',$c->text); + $this->assertEquals(6,$c->queryScalar()); + + $c=$builder->createDeleteCommand($table,new CDbCriteria(array( + 'condition'=>'id=:id', + 'params'=>array('id'=>6)))); + $this->assertEquals('DELETE FROM \'posts\' WHERE id=:id',$c->text); + $c->execute(); + $c=$builder->createCountCommand($table,new CDbCriteria); + $this->assertEquals(5,$c->queryScalar()); + + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'id, title', + 'condition'=>'id=:id', + 'params'=>array('id'=>5), + 'order'=>'title', + 'limit'=>2, + 'offset'=>0))); + $this->assertEquals('SELECT id, title FROM \'posts\' \'t\' WHERE id=:id ORDER BY title LIMIT 2',$c->text); + $rows=$c->query()->readAll(); + $this->assertEquals(1,count($rows)); + $this->assertEquals('post 5',$rows[0]['title']); + + $c=$builder->createUpdateCommand($table,array('title'=>'new post 5'),new CDbCriteria(array( + 'condition'=>'id=:id', + 'params'=>array('id'=>5)))); + $c->execute(); + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=:id', + 'params'=>array('id'=>5)))); + $this->assertEquals('new post 5',$c->queryScalar()); + + $c=$builder->createSqlCommand('SELECT title FROM posts \'t\' WHERE id=:id',array(':id'=>3)); + $this->assertEquals('post 3',$c->queryScalar()); + + $c=$builder->createUpdateCounterCommand($table,array('author_id'=>-2),new CDbCriteria(array('condition'=>'id=5'))); + $this->assertEquals('UPDATE \'posts\' SET "author_id"="author_id"-2 WHERE id=5',$c->text); + $c->execute(); + $c=$builder->createSqlCommand('SELECT author_id FROM posts WHERE id=5'); + $this->assertEquals(1,$c->queryScalar()); + + // test bind by position + $c=$builder->createFindCommand($table,new CDbCriteria(array( + 'select'=>'title', + 'condition'=>'id=?', + 'params'=>array(4)))); + $this->assertEquals('SELECT title FROM \'posts\' \'t\' WHERE id=?',$c->text); + $this->assertEquals('post 4',$c->queryScalar()); + + // another bind by position + $c=$builder->createUpdateCommand($table,array('title'=>'new post 4'),new CDbCriteria(array( + 'condition'=>'id=?', + 'params'=>array(4)))); + $c->execute(); + $c=$builder->createSqlCommand('SELECT title FROM posts WHERE id=4'); + $this->assertEquals('new post 4',$c->queryScalar()); + + // testCreateCriteria + $c=$builder->createCriteria('column=:value',array(':value'=>'value')); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c=$builder->createCriteria(array('condition'=>'column=:value','params'=>array(':value'=>'value'))); + $this->assertEquals('column=:value',$c->condition); + $this->assertEquals(array(':value'=>'value'),$c->params); + + $c2=$builder->createCriteria($c); + $this->assertTrue($c2!==$c); + $this->assertEquals('column=:value',$c2->condition); + $this->assertEquals(array(':value'=>'value'),$c2->params); + + // testCreatePkCriteria + $c=$builder->createPkCriteria($table,1,'author_id>1'); + $this->assertEquals('\'posts\'."id"=1 AND (author_id>1)',$c->condition); + + $c=$builder->createPkCriteria($table,array(1,2)); + $this->assertEquals('\'posts\'."id" IN (1, 2)',$c->condition); + + $c=$builder->createPkCriteria($table,array()); + $this->assertEquals('0=1',$c->condition); + + $table2=$schema->getTable('orders'); + $c=$builder->createPkCriteria($table2,array('key1'=>1,'key2'=>2),'name=\'\''); + $this->assertEquals('\'orders\'."key1"=1 AND \'orders\'."key2"=2 AND (name=\'\')',$c->condition); + + $c=$builder->createPkCriteria($table2,array(array('key1'=>1,'key2'=>2),array('key1'=>3,'key2'=>4))); + $this->assertEquals('\'orders\'."key1"||\',\'||\'orders\'."key2" IN (1||\',\'||2, 3||\',\'||4)',$c->condition); + + // createColumnCriteria + $c=$builder->createColumnCriteria($table,array('id'=>1,'author_id'=>2),'title=\'\''); + $this->assertEquals('\'posts\'."id"=:yp0 AND \'posts\'."author_id"=:yp1 AND (title=\'\')',$c->condition); + + $c=$builder->createPkCriteria($table2,array()); + $this->assertEquals('0=1',$c->condition); + } + + public function testResetSequence() + { + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->db->createCommand("DELETE FROM users")->execute(); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max2=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals($max+1,$max2); + + $userTable=$this->db->schema->getTable('users'); + + $this->db->createCommand("DELETE FROM users")->execute(); + $this->db->schema->resetSequence($userTable); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals(1,$max); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals(2,$max); + + $this->db->createCommand("DELETE FROM users")->execute(); + $this->db->schema->resetSequence($userTable,10); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals(10,$max); + $this->db->createCommand("INSERT INTO users (username, password, email) VALUES ('user4','pass4','email4')")->execute(); + $max=$this->db->createCommand("SELECT MAX(id) FROM users")->queryScalar(); + $this->assertEquals(11,$max); + } + + public function testCheckIntegrity1() + { + $this->db->schema->checkIntegrity(false); + $this->db->schema->checkIntegrity(true); + } + + public function testCheckIntegrity2() + { + $this->db->schema->checkIntegrity(true); + $this->assertEquals(0,$this->db->createCommand('SELECT COUNT(*) FROM profiles WHERE user_id=9999')->queryScalar()); + if(version_compare(PHP_VERSION,'5.3.0','>=')) + $this->setExpectedException('CDbException'); + $this->db->createCommand("INSERT INTO profiles (first_name,last_name,user_id) VALUES ('orphaned','profile',9999)")->execute(); + $this->assertEquals(1,$this->db->createCommand('SELECT COUNT(*) FROM profiles WHERE user_id=9999')->queryScalar()); + } + + public function testCheckIntegrity3() + { + $this->db->schema->checkIntegrity(false); + $this->assertEquals(0,$this->db->createCommand('SELECT COUNT(*) FROM profiles WHERE user_id=9999')->queryScalar()); + $this->db->createCommand("INSERT INTO profiles (first_name,last_name,user_id) VALUES ('orphaned','profile',9999)")->execute(); + $this->assertEquals(1,$this->db->createCommand('SELECT COUNT(*) FROM profiles WHERE user_id=9999')->queryScalar()); + } + + public function testRenameTable() + { + $this->db->schema->refresh(); + $this->assertArrayHasKey('profiles',$this->db->schema->tables); + $this->assertArrayHasKey('users',$this->db->schema->tables); + $this->assertArrayNotHasKey('profiles_renamed',$this->db->schema->tables); + $this->assertArrayNotHasKey('users_renamed',$this->db->schema->tables); + + $this->db->schema->refresh(); + $this->db->createCommand($this->db->schema->renameTable('profiles','profiles_renamed'))->execute(); + $this->db->createCommand($this->db->schema->renameTable('users','users_renamed'))->execute(); + + $this->db->schema->refresh(); + $this->assertArrayNotHasKey('profiles',$this->db->schema->tables); + $this->assertArrayNotHasKey('users',$this->db->schema->tables); + $this->assertArrayHasKey('profiles_renamed',$this->db->schema->tables); + $this->assertArrayHasKey('users_renamed',$this->db->schema->tables); + } + + public function testMultipleInsert() + { + $builder=$this->db->getSchema()->getCommandBuilder(); + $tableName='types'; + $data=array( + array( + 'int_col'=>1, + 'char_col'=>'char_col_1', + 'char_col2'=>'char_col_2_1', + 'float_col'=>1.1, + 'bool_col'=>true, + ), + array( + 'int_col'=>2, + 'char_col'=>'char_col_2', + 'float_col'=>2.2, + 'bool_col'=>false, + ), + ); + $command=$builder->createMultipleInsertCommand($tableName,$data); + $command->execute(); + + $rows=$builder->dbConnection->createCommand('SELECT * FROM '.$builder->dbConnection->quoteTableName($tableName))->queryAll(); + + $this->assertEquals(count($data),count($rows),'Records count miss matches!'); + foreach($rows as $rowIndex=>$row) + foreach($row as $columnName=>$value) + { + $columnIndex=array_search($columnName,$data[$rowIndex],true); + if($columnIndex==false) + continue; + $expectedValue=$data[$rowIndex][$columnIndex]; + $this->assertTrue($expectedValue==$value,"Value for column '{$columnName}' incorrect!"); + } + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CDateFormatterTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CDateFormatterTest.php new file mode 100644 index 0000000..0f62c6b --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CDateFormatterTest.php @@ -0,0 +1,87 @@ +dateFormatter->format("W",mktime(0,0,0,$month,$day,$year)); + //echo sprintf("%d/%d/%d\t%d\n",$year,$month,$day,$weekNum); + } + } + + //echo "Week number for 2011/01/01 is ".Yii::app()->dateFormatter->format("W",mktime(0,0,0,1,1,2011)); + //echo "Week number for 2011/01/07 is ".Yii::app()->dateFormatter->format("W",mktime(0,0,0,1,7,2011)); + } + + public function testStringIntegerDate() + { + date_default_timezone_set('UTC'); + $this->assertEquals('2012 09 03 07:54:09', Yii::app()->dateFormatter->format("yyyy MM dd hh:mm:ss", 1346702049)); + $this->assertEquals('2012 09 03 07:54:09', Yii::app()->dateFormatter->format("yyyy MM dd hh:mm:ss", '1346702049')); + $this->assertEquals('1927 04 30 04:05:51', Yii::app()->dateFormatter->format("yyyy MM dd hh:mm:ss", -1346702049)); + $this->assertEquals('1927 04 30 04:05:51', Yii::app()->dateFormatter->format("yyyy MM dd hh:mm:ss", '-1346702049')); + } + + public function testStrToTimeDate() + { + date_default_timezone_set('UTC'); + $this->assertEquals('2012 09 03 09:54:09', Yii::app()->dateFormatter->format("yyyy MM dd hh:mm:ss", '2012-09-03 09:54:09 UTC')); + $this->assertEquals('1927 04 30 05:05:51', Yii::app()->dateFormatter->format("yyyy MM dd hh:mm:ss", '1927-04-30 05:05:51 UTC')); + } + + public function providerFormatWeekInMonth() + { + return array( + array('2012.06.01',1), + array('2012.06.02',1), + array('2012.06.03',1), + array('2012.06.09',2), + array('2012.06.10',2), + array('2012.06.16',3), + array('2012.06.17',3), + array('2012.06.23',4), + array('2012.06.24',4), + array('2012.06.30',5), + + array('2011.10.01',1), + array('2011.10.03',2), + array('2011.10.08',2), + array('2011.10.10',3), + array('2011.10.15',3), + array('2011.10.17',4), + array('2011.10.22',4), + array('2011.10.24',5), + array('2011.10.29',5), + array('2011.10.31',6), + + array('2012.12.23',4), + array('2012.12.30',5), + array('2012.12.31',6), + array('2013.01.01',1), + array('2013.01.02',1), + array('2013.01.07',2), + + array('2010.12.17',3), + array('2010.12.24',4), + array('2010.12.31',5), + array('2011.01.01',1), + array('2011.01.08',2), + array('2011.01.15',3), + ); + } + + /** + * @dataProvider providerFormatWeekInMonth + */ + public function testFormatWeekInMonth($date,$expected) + { + list($year,$month,$day)=explode('.',$date); + $this->assertEquals($expected,Yii::app()->dateFormatter->format('W',mktime(12,0,0,(int)$month,(int)$day,(int)$year))); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CLocaleTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CLocaleTest.php new file mode 100644 index 0000000..a2e0bba --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CLocaleTest.php @@ -0,0 +1,247 @@ + 'en', + ); + + new TestApplication($config); + Yii::app()->configure($config); + } + + function testRequiredDataExistence(){ + foreach($this->criticalLocaleCodes as $localeCode){ + $locale = Yii::app()->getLocale($localeCode); + // AM/PM + $this->assertNotNull($locale->getAMName(), "$localeCode: getAMName failed."); + $this->assertNotNull($locale->getPMName(), "$localeCode: getPMName failed."); + + // currency + $this->assertNotNull($locale->getCurrencySymbol("USD"), "$localeCode: getCurrencySymbol USD failed."); + $this->assertNotNull($locale->getCurrencySymbol("EUR"), "$localeCode: getCurrencySymbol EUR failed."); + + // numbers + $this->assertNotNull($locale->getNumberSymbol('decimal'), "$localeCode: getNumberSymbol failed."); + $this->assertNotNull($locale->getDecimalFormat(), "$localeCode: getDecimalFormat failed."); + $this->assertNotNull($locale->getCurrencyFormat(), "$localeCode: getCurrencyFormat failed."); + $this->assertNotNull($locale->getPercentFormat(), "$localeCode: getPercentFormat failed."); + $this->assertNotNull($locale->getScientificFormat(), "$localeCode: getScientificFormat failed."); + + // date and time formats + $this->assertNotNull($locale->getMonthName(1), "$localeCode: getMonthName 1 failed."); + $this->assertNotNull($locale->getMonthName(12, 'abbreviated'), "$localeCode: getMonthName 12 abbreviated failed."); + $this->assertNotNull($locale->getMonthName(1, 'narrow', true), "$localeCode: getMonthName 1 narrow standalone failed."); + $this->assertEquals(12, count($locale->getMonthNames()), "$localeCode: getMonthNames failed."); + $this->assertNotNull($locale->getWeekDayName(0), "$localeCode: getWeekDayName failed."); + $this->assertNotNull($locale->getWeekDayNames(), "$localeCode: getWeekDayNames failed."); + $this->assertNotNull($locale->getEraName(1), "$localeCode: getEraName failed."); + $this->assertNotNull($locale->getDateFormat(), "$localeCode: getDateFormat failed."); + $this->assertNotNull($locale->getTimeFormat(), "$localeCode: getTimeFormat failed."); + $this->assertNotNull($locale->getDateTimeFormat(), "$localeCode: getDateTimeFormat failed."); + + // ORIENTATION + $this->assertTrue(in_array($locale->getOrientation(), array('ltr', 'rtl')), "$localeCode: getOrientation failed."); + + // plurals + $l = explode('_', $localeCode); + if(!in_array($l[0], $this->noPlurals)){ + $pluralRules = $locale->getPluralRules(); + $this->assertNotEmpty($pluralRules, $localeCode.": no plural rules"); + } + } + } + + public function providerGetLocaleDisplayName() + { + return array( + array('de','en_US','amerikanisches englisch'), + array('de','en','englisch'), + array('de_DE','en_US','amerikanisches englisch'), + array('de_DE','en','englisch'), + + array('es_MX',null,null), + array('es_ES',null,null), + + // https://github.com/yiisoft/yii/issues/2087 + array('en_us','en','english'), + array('en_us','en_us','u.s. english'), + array('en_us','pt','portuguese'), + array('en_us','pt','portuguese'), + array('en_us','pt_br','brazilian portuguese'), + array('en_us','pt_pt','iberian portuguese'), + ); + } + + /** + * @dataProvider providerGetLocaleDisplayName + */ + public function testGetLocaleDisplayName($ctorLocale,$methodLocale,$assertion) + { + $locale=CLocale::getInstance($ctorLocale); + $this->assertEquals(mb_strtolower($assertion),mb_strtolower($locale->getLocaleDisplayName($methodLocale))); + } + + public function providerGetLanguage() + { + return array( + array('en','fr_FR','french'), + array('en','fr','french'), + array('en_US','fr_FR','french'), + array('en_US','fr','french'), + array('ru','de_DE','немецкий'), + array('ru','de','немецкий'), + array('ru_RU','de_DE','немецкий'), + array('ru_RU','de','немецкий'), + array('de','en_US','englisch'), + array('de','en','englisch'), + array('de_DE','en_US','englisch'), + array('de_DE','en','englisch'), + + array('es_MX',null,null), + array('es_ES',null,null), + + array('ru_RU','zh-Hans-CN','китайÑкий'), + array('en_US','zh-Hans-CN','chinese'), + array('ru_RU','zh-Hant-HK','китайÑкий'), + array('en_US','zh-Hant-HK','chinese'), + array('ru','zh-Hant-HK','китайÑкий'), + array('en','zh-Hant-HK','chinese'), + + // https://github.com/yiisoft/yii/issues/2087 + array('en_us','en','English'), + array('en_us','en_us','English'), + array('en_us','pt','Portuguese'), + array('en_us','pt','Portuguese'), + array('en_us','pt_br','Portuguese'), + array('en_us','pt_pt','Portuguese'), + ); + } + + /** + * @dataProvider providerGetLanguage + */ + public function testGetLanguage($ctorLocale,$methodLocale,$assertion) + { + $locale=CLocale::getInstance($ctorLocale); + $this->assertEquals(mb_strtolower($assertion),mb_strtolower($locale->getLanguage($methodLocale))); + } + + public function providerGetScript() + { + return array( + array('en','fr_FR',null), + array('en','fr',null), + array('en_US','fr_FR',null), + array('en_US','fr',null), + array('ru','de_DE',null), + array('ru','de',null), + array('ru_RU','de_DE',null), + array('ru_RU','de',null), + array('de','en_US',null), + array('de','en',null), + array('de_DE','en_US',null), + array('de_DE','en',null), + + array('es_MX',null,null), + array('es_ES',null,null), + + array('ru_RU','zh-Hans-CN','Упрощенный китайÑкий'), + array('en_US','zh-Hans-CN','Simplified Han'), + array('ru_RU','zh-Hant-HK','Традиционный китайÑкий'), + array('en_US','zh-Hant-HK','Traditional Han'), + array('ru','zh-Hant-HK','Традиционный китайÑкий'), + array('en','zh-Hant-HK','Traditional Han'), + ); + } + + /** + * @dataProvider providerGetScript + */ + public function testGetScript($ctorLocale,$methodLocale,$assertion) + { + $locale=CLocale::getInstance($ctorLocale); + $this->assertEquals($assertion,$locale->getScript($methodLocale)); + } + + public function providerGetTerritory() + { + return array( + array('en','fr_FR','France'), + array('en','fr',null), + array('en_US','fr_FR','France'), + array('en_US','fr',null), + array('ru','de_DE','ГерманиÑ'), + array('ru','de',null), + array('ru_RU','de_DE','ГерманиÑ'), + array('ru_RU','de',null), + array('de','en_US','Vereinigte Staaten'), + array('de','en',null), + array('de_DE','en_US','Vereinigte Staaten'), + array('de_DE','en',null), + + array('es_MX',null,null), + array('es_ES',null,null), + + array('ru_RU','zh-Hans-CN','Китай'), + array('en_US','zh-Hans-CN','China'), + array('ru_RU','zh-Hant-HK','Гонконг'), + array('en_US','zh-Hant-HK','Hong Kong'), + array('ru','zh-Hant-HK','Гонконг'), + array('en','zh-Hant-HK','Hong Kong'), + ); + } + + /** + * @dataProvider providerGetTerritory + */ + public function testGetTerritory($ctorLocale,$methodLocale,$assertion) + { + $locale=CLocale::getInstance($ctorLocale); + $this->assertEquals($assertion,$locale->getTerritory($methodLocale)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CNumberFormatterTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CNumberFormatterTest.php new file mode 100644 index 0000000..8368e01 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CNumberFormatterTest.php @@ -0,0 +1,70 @@ +usFormatter=new CNumberFormatter('en_us'); + $this->deFormatter=new CNumberFormatter('de'); + } + + public function testFormatCurrency() + { + $numbers=array( + array(0, '$0.00', '0,00 $'), + array(100, '$100.00', '100,00 $'), + array(-100, '($100.00)', '-100,00 $'), + array(100.123, '$100.12', '100,12 $'), + array(100.1, '$100.10', '100,10 $'), + array(100.126, '$100.13', '100,13 $'), + array(1000.126, '$1,000.13', '1.000,13 $'), + array(1000000.123, '$1,000,000.12', '1.000.000,12 $'), + ); + + foreach($numbers as $number) + { + $this->assertEquals($number[1],$this->usFormatter->formatCurrency($number[0],'USD')); + $this->assertEquals($number[2],$this->deFormatter->formatCurrency($number[0],'USD')); + } + } + + public function testFormatDecimal() + { + $numbers=array( + array(0, '0', '0'), + array(100, '100', '100'), + array(-100, '-100', '-100'), + array(100.123, '100.123', '100,123'), + array(100.1, '100.1', '100,1'), + array(100.1206, '100.121', '100,121'), + array(1000.1206, '1,000.121', '1.000,121'), + array(1000000.123, '1,000,000.123', '1.000.000,123'), + ); + + foreach($numbers as $number) + { + $this->assertEquals($number[1],$this->usFormatter->formatDecimal($number[0])); + $this->assertEquals($number[2],$this->deFormatter->formatDecimal($number[0])); + } + } + + public function testFormatPercentage() + { + $numbers=array( + array(0, '0%', '0 %'), + array(0.123, '12%', '12 %'), + array(-0.123, '-12%', '-12 %'), + array(10.12, '1,012%', '1.012 %'), + array(10000.1, '1,000,010%', '1.000.010 %'), + ); + + foreach($numbers as $number) + { + $this->assertEquals($number[1],$this->usFormatter->formatPercentage($number[0])); + $this->assertEquals($number[2],$this->deFormatter->formatPercentage($number[0])); + } + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CPhpMessageSourceTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CPhpMessageSourceTest.php new file mode 100644 index 0000000..104e0a8 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/CPhpMessageSourceTest.php @@ -0,0 +1,18 @@ +setLanguage('de_DE'); + Yii::app()->messages->extensionPaths['MyTestExtension'] = 'CPhpMessageSourceTestRoot.messages'; + $this->assertEquals('Hallo Welt!', Yii::t('MyTestExtension.testcategory', 'Hello World!')); + } + + public function testModuleTranslation() + { + Yii::app()->setLanguage('de_DE'); + $this->assertEquals('Hallo Welt!', Yii::t('CPhpMessageSourceTest.testcategory', 'Hello World!')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/YiiTTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/YiiTTest.php new file mode 100644 index 0000000..43cb783 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/YiiTTest.php @@ -0,0 +1,191 @@ + 'es', + 'components' => array( + 'messages' => array( + 'class' => 'CPhpMessageSource', + 'basePath' => dirname(__FILE__).'/data', + //'forceTranslation' => true, + ), + ), + ); + + new TestApplication($config); + Yii::app()->configure($config); + } + + function tearDown() + { + Yii::app()->sourceLanguage = 'en_us'; + } + + // Simple: 'msg' + function testSimple(){ + Yii::app()->setLanguage('ru'); + $this->assertEquals('апельÑины', Yii::t('test', 'oranges')); + } + + function testSimpleSameLanguage(){ + Yii::app()->setLanguage('es'); + $this->assertEquals('no_changes', Yii::t('test', 'no_changes')); + } + + function testSimplePlaceholders(){ + Yii::app()->setLanguage('ru'); + $this->assertEquals('Ñумочки caviar', Yii::t('test', '{brand} bags', array('{brand}' => 'caviar'))); + $this->assertEquals('в корзине: 10', Yii::t('test', 'in the cart: {n}', 10)); + } + + function testSimplePlaceholdersSameLanguage(){ + Yii::app()->setLanguage('es'); + $this->assertEquals('10 changes', Yii::t('test', '{n} changes', 10)); + } + + // Plural: 'msg1|msg2|msg3' + function testPlural(){ + // CLDR + Yii::app()->setLanguage('ru'); + + // array notation + $this->assertEquals('огурец', Yii::t('test', 'cucumber|cucumbers', array(1))); + + //ru + $this->assertEquals('огурец', Yii::t('test', 'cucumber|cucumbers', 1)); + $this->assertEquals('огурец', Yii::t('test', 'cucumber|cucumbers', 101)); + $this->assertEquals('огурец', Yii::t('test', 'cucumber|cucumbers', 51)); + $this->assertEquals('огурца', Yii::t('test', 'cucumber|cucumbers', 2)); + $this->assertEquals('огурца', Yii::t('test', 'cucumber|cucumbers', 62)); + $this->assertEquals('огурца', Yii::t('test', 'cucumber|cucumbers', 104)); + $this->assertEquals('огурцов', Yii::t('test', 'cucumber|cucumbers', 5)); + $this->assertEquals('огурцов', Yii::t('test', 'cucumber|cucumbers', 78)); + $this->assertEquals('огурцов', Yii::t('test', 'cucumber|cucumbers', 320)); + $this->assertEquals('огурцов', Yii::t('test', 'cucumber|cucumbers', 0)); + + // fractions (you should specify fourh variant to use these in Russian) + $this->assertEquals('огурца', Yii::t('test', 'cucumber|cucumbers', 1.5)); + + // en + Yii::app()->setLanguage('en'); + + $this->assertEquals('cucumber', Yii::t('test', 'cucumber|cucumbers', 1)); + $this->assertEquals('cucumbers', Yii::t('test', 'cucumber|cucumbers', 2)); + $this->assertEquals('cucumbers', Yii::t('test', 'cucumber|cucumbers', 0)); + + // short forms + Yii::app()->setLanguage('ru'); + + $this->assertEquals('огурец', Yii::t('test', 'cucumber|cucumbers', 1)); + + // explicit params + $this->assertEquals('огурец', Yii::t('test', 'cucumber|cucumbers', array(0 => 1))); + } + + function testPluralPlaceholders(){ + Yii::app()->setLanguage('ru'); + + $this->assertEquals('1 огурец', Yii::t('test', '{n} cucumber|{n} cucumbers', 1)); + $this->assertEquals('2 огурца', Yii::t('test', '{n} cucumber|{n} cucumbers', 2)); + $this->assertEquals('5 огурцов', Yii::t('test', '{n} cucumber|{n} cucumbers', 5)); + + // more placeholders + $this->assertEquals('+ 5 огурцов', Yii::t('test', '{sign} {n} cucumber|{sign} {n} cucumbers', array(5, '{sign}' => '+'))); + + // placeholder swapping + $this->assertEquals('один огурец', Yii::t('test', '{n} cucumber|{n} cucumbers', array(1, '{n}' => 'один'))); + } + + /** + * If there are useless params in translation just ignore them. + */ + function testPluralMoreVariants(){ + Yii::app()->setLanguage('ru'); + $this->assertEquals('шлÑпы', Yii::t('test', 'hat|hats', array(2))); + } + + /** + * If there are less variants in translation like + * 'zombie|zombies' => 'зомби' (CLDR requires 3 variants for Russian + * but zombie is too special to be plural) + * + * Same for Chinese but there are no plurals at all. + */ + function testPluralLessVariants(){ + // three variants are required and only one specified (still valid for + // Russian in some special cases) + Yii::app()->setLanguage('ru'); + $this->assertEquals('зомби', Yii::t('test', 'zombie|zombies', 10)); + $this->assertEquals('зомби', Yii::t('test', 'zombie|zombies', 1)); + + // language with no plurals + Yii::app()->setLanguage('zh_cn'); + $this->assertEquals('k-s', Yii::t('test', 'kiss|kisses', 1)); + + // 3 variants are required while only 2 specified + // this one is synthetic but still good to know it at least does not + // produce error + Yii::app()->setLanguage('ru'); + $this->assertEquals('Ñин1', Yii::t('test', 'syn1|syn2|syn3', 1)); + $this->assertEquals('Ñин2', Yii::t('test', 'syn1|syn2|syn3', 2)); + $this->assertEquals('Ñин2', Yii::t('test', 'syn1|syn2|syn3', 5)); + } + + function pluralLessVariantsInSource(){ + // new doesn't have two forms in English + Yii::app()->setLanguage('ru'); + $this->assertEquals('новоÑти', Yii::t('test', 'news', 2)); + } + + function testPluralSameLanguage(){ + Yii::app()->setLanguage('es'); + + $this->assertEquals('cucumbez', Yii::t('test', 'cucumbez|cucumberz', 1)); + $this->assertEquals('cucumberz', Yii::t('test', 'cucumbez|cucumberz', 2)); + $this->assertEquals('cucumberz', Yii::t('test', 'cucumbez|cucumberz', 0)); + } + + function testPluralPlaceholdersSameLanguage(){ + Yii::app()->setLanguage('es'); + + $this->assertEquals('1 cucumbez', Yii::t('test', '{n} cucumbez|{n} cucumberz', 1)); + $this->assertEquals('2 cucumberz', Yii::t('test', '{n} cucumbez|{n} cucumberz', 2)); + $this->assertEquals('5 cucumberz', Yii::t('test', '{n} cucumbez|{n} cucumberz', 5)); + } + + // Choice: 'expr1#msg1|expr2#msg2|expr3#msg3' + function testChoice(){ + Yii::app()->setLanguage('ru'); + + // simple choices + $this->assertEquals('одна книга', Yii::t('test', 'n==1#one book|n>1#many books', 1)); + $this->assertEquals('много книг', Yii::t('test', 'n==1#one book|n>1#many books', 10)); + $this->assertEquals('одна книга', Yii::t('test', '1#one book|n>1#many books', 1)); + $this->assertEquals('много книг', Yii::t('test', '1#one book|n>1#many books', 10)); + } + + function testChoiceSameLanguage(){ + Yii::app()->setLanguage('es'); + + $this->assertEquals('one book', Yii::t('test', 'n==1#one book|n>1#many books', 1)); + $this->assertEquals('many books', Yii::t('test', 'n==1#one book|n>1#many books', 10)); + } + + function testChoicePlaceholders(){ + //$this->assertEquals('51 apples', Yii::t('app', '1#1apple|n>1|{n} apples', array(51, 'n'=>51))); + } + + function testChoicePlaceholdersSameLanguage(){ + + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/en/test.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/en/test.php new file mode 100644 index 0000000..41c4a79 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/en/test.php @@ -0,0 +1,4 @@ + 'cucumber|cucumbers', +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.mo b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.mo new file mode 100644 index 0000000000000000000000000000000000000000..17d9c33ed9700d3b9e3f3749419043e8e1d24d6c GIT binary patch literal 1422 zcma)5J#Q3A5FHM4!5|V+;I7D-0fUf`InbT>k|hHcEC>mb_H46mG}E)!(_=s)ut7k8 z00}`tz()p|Sv;^9dkBb;dj0_afd9a&-u2o60VCB`S66ktSFd}&Zy$RW;QJG{6E+3g z3cCg4?+xr5>@Dme?E0o4*a5%gkAdF}zYFmZ_#g0>;lHA0a&r(6;%!@k;BWXC{xA45 z@VuYFqbwMMp>*_NJ3x!k$GrTPCX9 zN$RE|kw(~sjx_5j>KHMn+QOsc#y0_jIe|U} z&7?xN0oyK>ht32*OVJi_c&5~e-z!8{NlhB@9um|w(yB5;oTefUM$`OWeK;-CR6>9P zd}&t9C@ZwZux3V)H3}1RqL5l9mPN6o>1MHn3yR{Fi@oSai!v9>iO3LCYI&_yb2ZYIb;U}H1-XSn#clL?i^NuC`Ir-bg5 zq9dc06dC%Ro;-bG9dbP07arrsqtWqZ7l8bZ_TqggeVCG2VG3!FTxgw)4z1TQ@>OY~ z6FSN9W;zpe2%3kNqEnC${3v z?Ut~t-7+>8k;XbE_tKXvH4E5T#F5Ybz-sfreIg$$Hw!qw?CJ=M%B`Sk6}A25K0p?b z=yN4DVZe4Dsd>zO@Cy>?`#5x8xJPpr;9Rll-lL%JAvd;JA=e{Rf;WKBv_`;;d#>6; zyduC?=)-70aw}Y3gUNvPU{oCZGDKQp6hu`s505kke&XZ%UV_0fs1xGAuhe-3sEgS!(ye%jNa$L9=(Lgt|OAs5Or`&r%QM{2lUf;GX+?t8s29t{(tEEX)!L zUPIS;te4%Qm&L0xPne+R7Lk97aqmFnnnlFT`3tLX@wntTKwn&3a~pq^wI%;u*477t EpDRg;bN~PV literal 0 HcmV?d00001 diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.php new file mode 100644 index 0000000..f03f729 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.php @@ -0,0 +1,15 @@ + 'апельÑины', + '{brand} bags' => 'Ñумочки {brand}', + 'in the cart: {n}' => 'в корзине: {n}', + 'cucumber|cucumbers' => 'огурец|огурца|огурцов|огурца', + '{n} cucumber|{n} cucumbers' => '{n} огурец|{n} огурца|{n} огурцов', + '{sign} {n} cucumber|{sign} {n} cucumbers' => '{sign} {n} огурец|{sign} {n} огурца|{sign} {n} огурцов', + 'zombie|zombies' => 'зомби', + 'hat|hats' => 'шлÑпа|шлÑпы|шлÑп|useless1|useless2', + 'news' => 'новоÑть|новоÑти|новоÑтей', + 'syn1|syn2|syn3' => 'Ñин1|Ñин2', + 'n==1#one book|n>1#many books' => 'n==1#одна книга|n>1#много книг', + '1#one book|n>1#many books' => '1#одна книга|n>1#много книг', +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.po b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.po new file mode 100644 index 0000000..83b5800 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/ru/test.po @@ -0,0 +1,56 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: resurtm \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.5\n" + +msgctxt "context1" +msgid "" +"Aliquam tempus elit vel purus molestie placerat. In sollicitudin tincidunt\n" +"aliquet. Integer tincidunt gravida tempor. In convallis blandit dui vel " +"malesuada.\n" +"Nunc vel sapien nunc, a pretium nulla." +msgstr "" +"Олицетворение однократно. ПредÑтавленный лекÑико-ÑемантичеÑкий анализ " +"ÑвлÑетÑÑ\n" +"пÑихолингвиÑтичеÑким в Ñвоей оÑнове, но механизм Ñочленений полидиÑперÑен. " +"Впечатление\n" +"однократно. Различное раÑположение выбирает Ñюжетный механизм Ñочленений." + +msgctxt "context1" +msgid "String number two." +msgstr "Строка номер два." + +msgctxt "context2" +msgid "\n\nThe other context.\n" +msgstr "\n\nДругой контекÑÑ‚.\n" + +msgctxt "context1" +msgid "Missing\n\r\t\"translation." +msgstr "\n\r\t\"" + +msgctxt "context1" +msgid "" +"Nunc vel sapien nunc, a pretium nulla.\n" +"Pellentesque habitant morbi tristique senectus et netus et malesuada fames " +"ac turpis egestas." +msgstr "Короткий перевод." + +msgid "contextless" +msgstr "" + +msgctxt "context2" +msgid "" +"test1\\ntest2\n" +"\\\n" +"test3" +msgstr "" +"теÑÑ‚1\\nтеÑÑ‚2\n" +"\\\n" +"теÑÑ‚3" diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/zh_cn/test.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/zh_cn/test.php new file mode 100644 index 0000000..0b286b3 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/data/zh_cn/test.php @@ -0,0 +1,4 @@ + 'k-s', +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/gettext/CGettextPoFileTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/gettext/CGettextPoFileTest.php new file mode 100644 index 0000000..3251ee6 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/gettext/CGettextPoFileTest.php @@ -0,0 +1,34 @@ +load($poFilePath,'context1'); + $context2=$poFile->load($poFilePath,'context2'); + + // item count + $this->assertCount(4,$context1); + $this->assertCount(2,$context2); + + // original messages + $this->assertArrayHasKey("Missing\n\r\t\"translation.",$context1); + $this->assertArrayHasKey("Aliquam tempus elit vel purus molestie placerat. In sollicitudin tincidunt\naliquet. Integer tincidunt gravida tempor. In convallis blandit dui vel malesuada.\nNunc vel sapien nunc, a pretium nulla.",$context1); + $this->assertArrayHasKey("String number two.",$context1); + $this->assertArrayHasKey("Nunc vel sapien nunc, a pretium nulla.\nPellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.",$context1); + + $this->assertArrayHasKey("\n\nThe other context.\n",$context2); + $this->assertArrayHasKey("test1\\\ntest2\n\\\\\ntest3",$context2); + + // translated messages + $this->assertTrue(in_array("\n\r\t\"",$context1)); + $this->assertTrue(in_array("Олицетворение однократно. ПредÑтавленный лекÑико-ÑемантичеÑкий анализ ÑвлÑетÑÑ\nпÑихолингвиÑтичеÑким в Ñвоей оÑнове, но механизм Ñочленений полидиÑперÑен. Впечатление\nоднократно. Различное раÑположение выбирает Ñюжетный механизм Ñочленений.",$context1)); + $this->assertTrue(in_array('Строка номер два.',$context1)); + $this->assertTrue(in_array('Короткий перевод.',$context1)); + + $this->assertTrue(in_array("\n\nДругой контекÑÑ‚.\n",$context2)); + $this->assertTrue(in_array("теÑÑ‚1\\\nтеÑÑ‚2\n\\\\\nтеÑÑ‚3",$context2)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/messages/de_DE/testcategory.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/messages/de_DE/testcategory.php new file mode 100644 index 0000000..e2a976f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/i18n/messages/de_DE/testcategory.php @@ -0,0 +1,5 @@ + 'Hallo Welt!', +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CDateTimeParserTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CDateTimeParserTest.php new file mode 100644 index 0000000..c5f0f86 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CDateTimeParserTest.php @@ -0,0 +1,217 @@ +assertEquals( + '02 Aug, 2010, 05:09:07', + date('d M, Y, H:i:s', CDateTimeParser::parse('XX, 2.8.10, 5:9:7 AM', '??, d.M.yy, h:m:s a')) + ); + $this->assertEquals( + '02 Aug, 2010, 05:09:07', + date('d M, Y, H:i:s', CDateTimeParser::parse('02/08/2010, yyy, 05:9:7', 'dd/MM/yyyy, ???, hh:m:s')) + ); + $this->assertEquals( + '02 Aug, 2010, 05:09:07', + date('d M, Y, H:i:s', CDateTimeParser::parse('2\AUG\2010, 5:09:07 Am, ZzZ', 'd\MMM\yyyy, H:mm:ss a, ???')) + ); + $this->assertEquals( + '02 Aug, 2010, 05:09:07', + date('d M, Y, H:i:s', CDateTimeParser::parse('02_augUST|10, W, 05-09-07', 'dd_MMMM|yy, ?, HH-mm-ss')) + ); + } + + public function testParseDefaults() + { + $this->assertEquals( + '31-12-2011 23:59:59', + date('d-m-Y H:i:s', CDateTimeParser::parse('2011-12-31', 'yyyy-MM-dd', array('hour' => 23, 'minute' => 59, 'second' => 59))) + ); + // test matching with wildcards, this example is mssql timestamp + $this->assertEquals( + '2011-02-10 23:43:04', + date('Y-m-d H:i:s', CDateTimeParser::parse('2011-02-10 23:43:04.973', 'yyyy-MM-dd hh:mm:ss.???')) + ); + $this->assertEquals( + '2011-01-10 23:43:04', + date('Y-m-d H:i:s', CDateTimeParser::parse('2011-01-10 23:43:04.973', 'yyyy?MM?dd?hh?mm?ss????')) + ); + } + + public function testShortMonthTitle() + { + $this->assertEquals( + '21 Sep, 2011, 13:37', + date('d M, Y, H:i', CDateTimeParser::parse('21 SEP, 2011, 13:37', 'dd MMM, yyyy, HH:mm')) + ); + $this->assertEquals( + '05, 1991, 01:09, Mar', + date('d, Y, H:i, M', CDateTimeParser::parse('05, 1991, 01:09, mar', 'dd, yyyy, HH:mm, MMM')) + ); + $this->assertEquals( + 'Dec 01, 1971, 23:59', + date('M d, Y, H:i', CDateTimeParser::parse('Dec 01, 1971, 23:59', 'MMM dd, yyyy, HH:mm')) + ); + } + + public function testMonthTitle() + { + $this->assertEquals( + '21 Sep, 2011, 13:37', + date('d M, Y, H:i', CDateTimeParser::parse('21 September, 2011, 13:37', 'dd MMMM, yyyy, HH:mm')) + ); + $this->assertEquals( + '05, 1991, 01:09, Mar', + date('d, Y, H:i, M', CDateTimeParser::parse('05, 1991, 01:09, march', 'dd, yyyy, HH:mm, MMMM')) + ); + $this->assertEquals( + 'Dec 01, 1971, 23:59', + date('M d, Y, H:i', CDateTimeParser::parse('DECEMBER 01, 1971, 23:59', 'MMMM dd, yyyy, HH:mm')) + ); + } + + public function testLocaleShortMonthTitle() + { + // remember active application language and charset + $oldLanguage=Yii::app()->getLanguage(); + $oldCharset=Yii::app()->charset; + + // ru_RU.UTF-8 + Yii::app()->setLanguage('ru_RU'); + Yii::app()->charset='UTF-8'; + $this->assertEquals( + '21 Sep, 2011, 13:37', + date('d M, Y, H:i', CDateTimeParser::parse('21 СЕÐТ, 2011, 13:37', 'dd MMM, yyyy, HH:mm')) + ); + $this->assertEquals( + '05, 1991, 01:09, Mar', + date('d, Y, H:i, M', CDateTimeParser::parse('05, 1991, 01:09, март', 'dd, yyyy, HH:mm, MMM')) + ); + $this->assertEquals( + 'Dec 01, 1971, 23:59', + date('M d, Y, H:i', CDateTimeParser::parse('Дек 01, 1971, 23:59', 'MMM dd, yyyy, HH:mm')) + ); + + // de_DE.UTF-8 + Yii::app()->setLanguage('de_DE'); + Yii::app()->charset='UTF-8'; + $this->assertEquals( + '21 Sep, 2011, 13:37', + date('d M, Y, H:i', CDateTimeParser::parse('21 sep, 2011, 13:37', 'dd MMM, yyyy, HH:mm')) + ); + $this->assertEquals( + '05, 1991, 01:09, Mar', + date('d, Y, H:i, M', CDateTimeParser::parse('05, 1991, 01:09, mär', 'dd, yyyy, HH:mm, MMM')) + ); + $this->assertEquals( + 'Dec 01, 1971, 23:59', + date('M d, Y, H:i', CDateTimeParser::parse('Dez 01, 1971, 23:59', 'MMM dd, yyyy, HH:mm')) + ); + + // zh_CN.UTF-8 + Yii::app()->setLanguage('zh_CN'); + Yii::app()->charset='UTF-8'; + $this->assertEquals( + '21 Sep, 2011, 13:37', + date('d M, Y, H:i', CDateTimeParser::parse('21 乿œˆ, 2011, 13:37', 'dd MMM, yyyy, HH:mm')) + ); + $this->assertEquals( + '05, 1991, 01:09, Mar', + date('d, Y, H:i, M', CDateTimeParser::parse('05, 1991, 01:09, 三月', 'dd, yyyy, HH:mm, MMM')) + ); + $this->assertEquals( + 'Dec 01, 1971, 23:59', + date('M d, Y, H:i', CDateTimeParser::parse('å二月 01, 1971, 23:59', 'MMM dd, yyyy, HH:mm')) + ); + + // reestablish old active language and charset + Yii::app()->setLanguage($oldLanguage); + Yii::app()->charset=$oldCharset; + } + + public function testLocaleMonthTitle() + { + // remember active application language and charset + $oldLanguage=Yii::app()->getLanguage(); + $oldCharset=Yii::app()->charset; + + // ru_RU.UTF-8 + Yii::app()->setLanguage('ru_RU'); + Yii::app()->charset='UTF-8'; + $this->assertEquals( + '21 Sep, 2011, 13:37', + date('d M, Y, H:i', CDateTimeParser::parse('21 СЕÐТЯБРЯ, 2011, 13:37', 'dd MMMM, yyyy, HH:mm')) + ); + $this->assertEquals( + '05, 1991, 01:09, Mar', + date('d, Y, H:i, M', CDateTimeParser::parse('05, 1991, 01:09, март', 'dd, yyyy, HH:mm, MMMM')) + ); + $this->assertEquals( + 'Dec 01, 1971, 23:59', + date('M d, Y, H:i', CDateTimeParser::parse('Ð”ÐµÐºÐ°Ð±Ñ€Ñ 01, 1971, 23:59', 'MMMM dd, yyyy, HH:mm')) + ); + + // de_DE.UTF-8 + Yii::app()->setLanguage('de_DE'); + Yii::app()->charset='UTF-8'; + $this->assertEquals( + '21 Sep, 2011, 13:37', + date('d M, Y, H:i', CDateTimeParser::parse('21 SEPTEMBER, 2011, 13:37', 'dd MMMM, yyyy, HH:mm')) + ); + $this->assertEquals( + '05, 1991, 01:09, Mar', + date('d, Y, H:i, M', CDateTimeParser::parse('05, 1991, 01:09, März', 'dd, yyyy, HH:mm, MMMM')) + ); + $this->assertEquals( + 'Dec 01, 1971, 23:59', + date('M d, Y, H:i', CDateTimeParser::parse('dezember 01, 1971, 23:59', 'MMMM dd, yyyy, HH:mm')) + ); + + // zh_CN.UTF-8 + Yii::app()->setLanguage('zh_CN'); + Yii::app()->charset='UTF-8'; + $this->assertEquals( + '21 Sep, 2011, 13:37', + date('d M, Y, H:i', CDateTimeParser::parse('21 乿œˆ, 2011, 13:37', 'dd MMMM, yyyy, HH:mm')) + ); + $this->assertEquals( + '05, 1991, 01:09, Mar', + date('d, Y, H:i, M', CDateTimeParser::parse('05, 1991, 01:09, 三月', 'dd, yyyy, HH:mm, MMMM')) + ); + $this->assertEquals( + 'Dec 01, 1971, 23:59', + date('M d, Y, H:i', CDateTimeParser::parse('å二月 01, 1971, 23:59', 'MMMM dd, yyyy, HH:mm')) + ); + + // reestablish old active language and charset + Yii::app()->setLanguage($oldLanguage); + Yii::app()->charset=$oldCharset; + } + + public function testFailing() + { + // empty parsed string + $this->assertFalse(CDateTimeParser::parse('', 'dd MMMM, yyyy, HH:mm')); + $this->assertFalse(CDateTimeParser::parse(false, 'dd MMMM, yyyy, HH:mm')); + $this->assertFalse(CDateTimeParser::parse(null, 'dd MMMM, yyyy, HH:mm')); + + // accidently mixed up arguments + $this->assertFalse(CDateTimeParser::parse('dd/MM/yyyy, ???, hh:m:s', '02/08/2010, yyy, 05:9:7')); + $this->assertFalse(CDateTimeParser::parse('yyyy-MM-dd', '2011-12-31', array('hour' => 23, 'minute' => 59, 'second' => 59))); + + // current locale is not ru_RU.UTF-8 + $this->assertFalse(CDateTimeParser::parse('21 СЕÐТЯБРЯ, 2011, 13:37', 'dd MMMM, yyyy, HH:mm')); + + // current locale is not zh_CN.UTF-8 + $this->assertFalse(CDateTimeParser::parse('21 乿œˆ, 2011, 13:37', 'dd MMMM, yyyy, HH:mm')); + + // wrong first slash in the parsed string + $this->assertFalse(CDateTimeParser::parse('02\08/2010, yyy, 05:9:7', 'dd/MM/yyyy, ???, hh:m:s')); + + // inexistent patterns + $this->assertFalse(CDateTimeParser::parse('05, 1991, 01:09, mar', 'dd, yyyy, HH:mm, MMMMM')); // illegal month pattern + $this->assertFalse(CDateTimeParser::parse('05, 1991, 01:09, mar', 'ddd, yyyy, HH:mm, MMM')); // illegal day pattern + $this->assertFalse(CDateTimeParser::parse('05, 1991, 01:09, mar', 'dd, yyyyy, HH:mm, MMM')); // illegal year pattern + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CFileHelperTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CFileHelperTest.php new file mode 100644 index 0000000..d3ef420 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CFileHelperTest.php @@ -0,0 +1,163 @@ +testDir=Yii::getPathOfAlias('application.runtime.CFileHelper'); + if(!is_dir($this->testDir) && !(@mkdir($this->testDir))) + $this->markTestIncomplete('Unit tests runtime directory should have writable permissions!'); + + // create temporary testing data files + $filesData=array( + 'mimeTypes1.php'=>"'application/json','txb'=>'another/mime');", + 'mimeTypes2.php'=>"'text/plain','txb'=>'another/mime2');", + ); + foreach($filesData as $fileName=>$fileData) + if(!(@file_put_contents($this->testDir.$fileName,$fileData))) + $this->markTestIncomplete('Unit tests runtime directory should have writable permissions!'); + } + + protected function tearDown() + { + if (is_dir($this->testDir)) + $this->rrmdir($this->testDir); + } + + public function testGetMimeTypeByExtension() + { + // run everything ten times in one test action to be sure that caching inside + // CFileHelper::getMimeTypeByExtension() is working the right way + for($i=0;$i<10;$i++) + { + $this->assertNull(CFileHelper::getMimeTypeByExtension('test.txa')); + $this->assertNull(CFileHelper::getMimeTypeByExtension('test.txb')); + $this->assertEquals('text/plain',CFileHelper::getMimeTypeByExtension('test.txt')); + + $this->assertEquals('application/json',CFileHelper::getMimeTypeByExtension('test.txa',$this->testDir.'mimeTypes1.php')); + $this->assertEquals('another/mime',CFileHelper::getMimeTypeByExtension('test.txb',$this->testDir.'mimeTypes1.php')); + $this->assertNull(CFileHelper::getMimeTypeByExtension('test.txt',$this->testDir.'mimeTypes1.php')); + + $this->assertNull(CFileHelper::getMimeTypeByExtension('test.txa',$this->testDir.'mimeTypes2.php')); + $this->assertEquals('another/mime2',CFileHelper::getMimeTypeByExtension('test.txb',$this->testDir.'mimeTypes2.php')); + $this->assertEquals('text/plain',CFileHelper::getMimeTypeByExtension('test.txt',$this->testDir.'mimeTypes2.php')); + } + } + + public function testCopyDirectory_subDir_modeShoudBe0775() + { + if (substr(PHP_OS,0,3)=='WIN') + $this->markTestSkipped("Can't reliably test it on Windows because fileperms() always return 0777."); + + $this->createTestStruct($this->testDir); + $src=$this->testDir.DIRECTORY_SEPARATOR.$this->rootDir1; + $dst=$this->testDir.DIRECTORY_SEPARATOR.$this->rootDir2; + CFileHelper::copyDirectory($src,$dst,array('newDirMode'=>$this->testMode)); + + $subDir2Mode=$this->getMode($dst.DIRECTORY_SEPARATOR.$this->subDir); + $expectedMode=sprintf('%o',$this->testMode); + $this->assertEquals($expectedMode,$subDir2Mode,"Subdir mode is not {$expectedMode}"); + } + + public function testCopyDirectory_subDir_modeShoudBe0777() + { + if (substr(PHP_OS,0,3)=='WIN') + $this->markTestSkipped("Can't reliably test it on Windows because fileperms() always return 0777."); + + $this->createTestStruct($this->testDir); + $src=$this->testDir.DIRECTORY_SEPARATOR.$this->rootDir1; + $dst=$this->testDir.DIRECTORY_SEPARATOR.$this->rootDir2; + CFileHelper::copyDirectory($src,$dst); + + $subDir2Mode=$this->getMode($dst.DIRECTORY_SEPARATOR.$this->subDir); + $expectedMode=sprintf('%o',0777); + $this->assertEquals($expectedMode,$subDir2Mode,"Subdir mode is not {$expectedMode}"); + } + + public function testRemoveDirectory() + { + $this->createTestStruct($this->testDir); + + $ds=DIRECTORY_SEPARATOR; + $bd=$this->testDir.$ds; + + $this->assertTrue(is_dir($bd.$this->rootDir1)); + $this->assertTrue(is_dir($bd.$this->rootDir1.$ds.$this->subDir)); + $this->assertFalse(is_dir($bd.$this->rootDir2)); + $this->assertTrue(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file1)); + $this->assertTrue(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file2)); + $this->assertTrue(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file3)); + $this->assertFalse(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file4)); + + CFileHelper::removeDirectory($bd.$this->rootDir2); + + $this->assertTrue(is_dir($bd.$this->rootDir1)); + $this->assertTrue(is_dir($bd.$this->rootDir1.$ds.$this->subDir)); + $this->assertFalse(is_dir($bd.$this->rootDir2)); + $this->assertTrue(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file1)); + $this->assertTrue(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file2)); + $this->assertTrue(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file3)); + $this->assertFalse(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file4)); + + CFileHelper::removeDirectory($bd); + + $this->assertFalse(is_dir($bd.$this->rootDir1)); + $this->assertFalse(is_dir($bd.$this->rootDir1.$ds.$this->subDir)); + $this->assertFalse(is_dir($bd.$this->rootDir2)); + $this->assertFalse(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file1)); + $this->assertFalse(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file2)); + $this->assertFalse(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file3)); + $this->assertFalse(is_file($bd.$this->rootDir1.$ds.$this->subDir.$ds.$this->file4)); + } + + private function createTestStruct($testDir) + { + $rootDir=$testDir.DIRECTORY_SEPARATOR.$this->rootDir1; + mkdir($rootDir); + + $subDir=$testDir.DIRECTORY_SEPARATOR.$this->rootDir1.DIRECTORY_SEPARATOR.$this->subDir; + mkdir($subDir); + + $file1=$testDir.DIRECTORY_SEPARATOR.$this->rootDir1.DIRECTORY_SEPARATOR.$this->subDir.DIRECTORY_SEPARATOR.$this->file1; + file_put_contents($file1,'12321312'); + + $file2=$testDir.DIRECTORY_SEPARATOR.$this->rootDir1.DIRECTORY_SEPARATOR.$this->subDir.DIRECTORY_SEPARATOR.$this->file2; + file_put_contents($file2,'.htaccess'); + + $file3=$testDir.DIRECTORY_SEPARATOR.$this->rootDir1.DIRECTORY_SEPARATOR.$this->subDir.DIRECTORY_SEPARATOR.$this->file3; + file_put_contents($file3,'..svn'); + } + + private function getMode($file) + { + return substr(sprintf('%o',fileperms($file)),-4); + } + + private function rrmdir($dir) + { + if($handle=opendir($dir)) + { + while(false!==($entry=readdir($handle))) + { + if($entry!="." && $entry!="..") + { + if(is_dir($dir."/".$entry)===true) + $this->rrmdir($dir."/".$entry); + else + unlink($dir."/".$entry); + } + } + closedir($handle); + rmdir($dir); + } + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CFormatterTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CFormatterTest.php new file mode 100644 index 0000000..c6a52e0 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CFormatterTest.php @@ -0,0 +1,126 @@ +language=null; // reset language to not affect other tests + } + + /** + * Test formatting size numbers in bytes, kilobytes, ... + */ + public function testSizeFormat() + { + $formatter = new CFormatter(); + + Yii::app()->language = 'en'; + $this->assertEquals('1 byte', $formatter->formatSize(1, true)); + $this->assertEquals('10 bytes', $formatter->formatSize(10, true)); + $this->assertEquals('1 kilobyte', $formatter->formatSize(1024, true)); + $this->assertEquals('1.5 kilobytes', $formatter->formatSize(1536, true)); + $this->assertEquals('1.51 kilobytes', $formatter->formatSize(1550, true)); + $formatter->sizeFormat['decimals']=3; + $this->assertEquals('1.514 kilobytes', $formatter->formatSize(1550, true)); + $formatter->sizeFormat['decimals']=4; + $this->assertEquals('1.5137 kilobytes', $formatter->formatSize(1550, true)); + + $this->assertEquals('1 B', $formatter->formatSize(1, false)); + $this->assertEquals('10 B', $formatter->formatSize(10, false)); + $this->assertEquals('1 KB', $formatter->formatSize(1024, false)); + $this->assertEquals('1.5 KB', $formatter->formatSize(1536, false)); + + $this->assertEquals('1 byte', $formatter->formatSize(1, true)); + $this->assertEquals('1 kilobyte', $formatter->formatSize(1024, true)); + $this->assertEquals('1 megabyte', $formatter->formatSize(1024 * 1024, true)); + $this->assertEquals('1 gigabyte', $formatter->formatSize(1024 * 1024 * 1024, true)); + $this->assertEquals('1 terabyte', $formatter->formatSize(1024 * 1024 * 1024 * 1024, true)); + + Yii::app()->language = 'de'; + $formatter->sizeFormat['decimalSeparator']=','; + $this->assertEquals('1 Byte', $formatter->formatSize(1, true)); + $this->assertEquals('10 Byte', $formatter->formatSize(10, true)); + $this->assertEquals('1 Kilobyte', $formatter->formatSize(1024, true)); + $this->assertEquals('1,5 Kilobyte', $formatter->formatSize(1536, true)); + } + + public function languages() + { + return array( + array('cs'), + array('de'), + array('ja'), + array('kk'), + array('ru'), + array('sk'), + array('uk'), + ); + } + + /** + * This test is to check whether messages get actually translated to non-english + * + * @dataProvider languages + * @param $language + */ + public function testSizeFormatTranslation($language) + { + $formatter = new CFormatter(); + + Yii::app()->language=$language; + + $this->assertNotEquals('1 byte', $formatter->formatSize(1, true)); + $this->assertNotEquals('1 kilobyte', $formatter->formatSize(1024, true)); + $this->assertNotEquals('1 megabyte', $formatter->formatSize(1024 * 1024, true)); + $this->assertNotEquals('1 gigabyte', $formatter->formatSize(1024 * 1024 * 1024, true)); + $this->assertNotEquals('1 terabyte', $formatter->formatSize(1024 * 1024 * 1024 * 1024, true)); + + // test sizeformat works with non integers + $formatter->sizeFormat['decimals']=4; + $this->assertNotEquals('1.5137 kilobytes', $formatter->formatSize(1550, true)); + } + + public function providerFormatNtext() + { + return array( + array( + "
              \nline2\n\nline3\n\n\nline4\n\n\n\nline5", + false, + false, + "<br/>
              \nline2
              \n
              \nline3
              \n
              \n
              \nline4
              \n
              \n
              \n
              \nline5", + ), + array( + "
              \nline2\n\nline3\n\n\nline4\n\n\n\nline5", + false, + true, + "<br/>
              \nline2
              \n
              \nline3
              \n
              \n
              \nline4
              \n
              \n
              \n
              \nline5", + ), + array( + "
              \nline2\n\nline3\n\n\nline4\n\n\n\nline5", + true, + false, + '

              <br/>

              line2

              line3

              line4

              line5

              ', + ), + array( + "
              \nline2\n\nline3\n\n\nline4\n\n\n\nline5", + true, + true, + '

              <br/>

              line2

              line3

              line4

              line5

              ', + ), + ); + } + + /** + * @dataProvider providerFormatNtext + * @param string $value + * @param string $paragraphs + * @param string $removeEmptyParagraphs + * @param string $assertion + */ + public function testFormatNtext($value, $paragraphs, $removeEmptyParagraphs, $assertion) + { + $formatter = new CFormatter(); + $this->assertEquals($assertion, $formatter->formatNtext($value, $paragraphs, $removeEmptyParagraphs)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CLocalizedFormatterTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CLocalizedFormatterTest.php new file mode 100644 index 0000000..20e2b40 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/utils/CLocalizedFormatterTest.php @@ -0,0 +1,33 @@ +language=null; // reset language to not affect other tests + } + + /** + * Test boolean format translation + */ + public function testBooleanFormat() + { + Yii::app()->setComponent('format', new CLocalizedFormatter()); + + $this->assertEquals('Yes', Yii::app()->format->boolean(true)); + $this->assertEquals('No', Yii::app()->format->boolean(false)); + + Yii::app()->setComponent('format', new CLocalizedFormatter()); + Yii::app()->setLanguage('de'); + + $this->assertEquals('Ja', Yii::app()->format->boolean(true)); + $this->assertEquals('Nein', Yii::app()->format->boolean(false)); + + Yii::app()->setComponent('format', new CLocalizedFormatter()); + Yii::app()->setLanguage('en_US'); + + $this->assertEquals('Yes', Yii::app()->format->boolean(true)); + $this->assertEquals('No', Yii::app()->format->boolean(false)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CBooleanValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CBooleanValidatorTest.php new file mode 100644 index 0000000..655c227 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CBooleanValidatorTest.php @@ -0,0 +1,104 @@ + + */ +class CBooleanValidatorTest extends CTestCase +{ + /** + * Test we can catch validation errors using custom false/true values + * + * @return null + */ + public function testValidationUsingCustomFalseTrueValues() + { + $model = $this->getModelMock(array('falseValue' => 'false', 'trueValue' => 'true')); + $model->foo = 'blah'; + $this->assertFalse($model->hasErrors('foo')); + + $model->foo = 'false'; + $this->assertTrue($model->validate()); + + // client script + $validator = new CBooleanValidator; + $validator->trueValue = 'foo'; + $validator->falseValue = 'bar'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertContains('Foo must be either foo or bar', $script); + } + + /** + * Test allow empty + * + * @return null + */ + public function testValidateAndAllowEmpty() + { + $model = $this->getModelMock(array('allowEmpty' => false)); + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + + $model = $this->getModelMock(array('allowEmpty' => true)); + $this->assertTrue($model->validate()); + } + + /** + * Test using strict + * + * @return null + */ + public function testValidationUsingStrict() + { + $model = $this->getModelMock(array('strict' => true)); + $model->foo = 1; + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + + $model->foo = '1'; + $this->assertTrue($model->hasErrors('foo')); + } + + /** + * Test array typed value + * https://github.com/yiisoft/yii/issues/1955 + * + * @return null + */ + public function testValidateArrayValue() + { + $model = $this->getModelMock(); + $model->foo = array(1); + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + $this->assertSame(array('Foo must be either 1 or 0.'), $model->getErrors('foo')); + } + + /** + * Mocks up an object to test with + * + * @param array $params additional parameters sent to rules + * + * @return null + */ + protected function getModelMock($params=array()) + { + $rules = array( + array('foo', 'boolean') + ); + + foreach ($params as $rule => $value) { + $rules[0][$rule] = $value; + } + + $stub = $this->getMock('ModelMock', array('rules')); + $stub->expects($this->any()) + ->method('rules') + ->will($this->returnValue($rules)); + + return $stub; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CCompareValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CCompareValidatorTest.php new file mode 100644 index 0000000..87c12ba --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CCompareValidatorTest.php @@ -0,0 +1,293 @@ + + */ +class CCompareValidatorTest extends CTestCase +{ + /** + * Test we can catch validation errors + * + * @return null + */ + public function testValidationErrorsWithEquals() + { + $model = $this->getModelMock(array('compareAttribute' => 'bar')); + $model->foo = 'foo'; + $model->bar = 'bar'; + + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + $model->bar = 'foo'; + $this->assertTrue($model->validate()); + + // https://github.com/yiisoft/yii/issues/1955 + $model->foo = array('foo'); + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + + // client validation + $validator = new CCompareValidator; + $validator->operator = '='; + $validator->compareAttribute = 'bar'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertInternalType('string', $script); + $this->assertContains('Foo must be repeated exactly.', $script); + } + + /** + * Test we can catch validation errors + * + * @return null + */ + public function testValidationErrorsWithNotEquals() + { + $model = $this->getModelMock(array( + 'operator' => '!=', + 'strict' => true, + 'compareAttribute' => 'bar', + )); + $model->foo = 'foo'; + $model->bar = 'bar'; + + $this->assertTrue($model->validate()); + + $model->bar = 'foo'; + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + + // client validation + $validator = new CCompareValidator; + $validator->operator = '!='; + $validator->compareAttribute = 'bar'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertInternalType('string', $script); + $this->assertContains('Foo must not be equal to \"{compareValue}\".".replace(\'{compareValue}\', ', $script); + + $validator->message = '{compareAttribute}'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertContains('"Bar"', $script); + $this->assertNotContains('{compareAttribute}', $script); + } + + /** + * Test we can catch validation errors + * + * @return null + */ + public function testValidationErrorsWitGreaterThan() + { + $model = $this->getModelMock(array( + 'operator' => '>', + 'strict' => true, + 'compareAttribute' => 'bar', + )); + $model->foo = 1; + $model->bar = 2; + + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + $model->bar = 0; + $this->assertTrue($model->validate()); + + // client validation + $validator = new CCompareValidator; + $validator->operator = '>'; + $validator->compareAttribute = 'bar'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertInternalType('string', $script); + $this->assertContains('Foo must be greater than \"{compareValue}\".".replace(\'{compareValue}\', ', $script); + + $validator->message = '{compareAttribute}'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertContains('"Bar"', $script); + $this->assertNotContains('{compareAttribute}', $script); + } + + /** + * Test we can catch validation errors + * + * @return null + */ + public function testValidationErrorsWitGreaterThanOrEqual() + { + $model = $this->getModelMock(array( + 'operator' => '>=', + 'strict' => true, + 'compareAttribute' => 'bar', + )); + $model->foo = 1; + $model->bar = 2; + + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + $model->bar = 1; + $this->assertTrue($model->validate()); + + // client validation + $validator = new CCompareValidator; + $validator->operator = '>='; + $validator->compareAttribute = 'bar'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertInternalType('string', $script); + $this->assertContains('Foo must be greater than or equal to \"{compareValue}\".".replace(\'{compareValue}\', ', $script); + + $validator->message = '{compareAttribute}'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertContains('"Bar"', $script); + $this->assertNotContains('{compareAttribute}', $script); + } + + /** + * Test we can catch validation errors + * + * @return null + */ + public function testValidationErrorsWitLessThan() + { + $model = $this->getModelMock(array( + 'operator' => '<', + 'strict' => true, + 'compareAttribute' => 'bar', + )); + $model->foo = 3; + $model->bar = 2; + + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + $model->bar = 4; + $this->assertTrue($model->validate()); + + // client validation + $validator = new CCompareValidator; + $validator->operator = '<'; + $validator->compareAttribute = 'bar'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertInternalType('string', $script); + $this->assertContains('Foo must be less than \"{compareValue}\".".replace(\'{compareValue}\', ', $script); + + $validator->message = '{compareAttribute}'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertContains('"Bar"', $script); + $this->assertNotContains('{compareAttribute}', $script); + } + + /** + * Test we can catch validation errors + * + * @return null + */ + public function testValidationErrorsWitLessThanOrEqual() + { + $model = $this->getModelMock(array( + 'operator' => '<=', + 'strict' => true, + 'compareAttribute' => 'bar', + )); + $model->foo = 3; + $model->bar = 2; + + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + $model->bar = 3; + $this->assertTrue($model->validate()); + + // client validation + $validator = new CCompareValidator; + $validator->operator = '<='; + $validator->compareAttribute = 'bar'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertInternalType('string', $script); + $this->assertContains('Foo must be less than or equal to \"{compareValue}\".".replace(\'{compareValue}\', ', $script); + + $validator->message = '{compareAttribute}'; + $script = $validator->clientValidateAttribute($model, 'foo'); + $this->assertContains('"Bar"', $script); + $this->assertNotContains('{compareAttribute}', $script); + } + + /** + * @expectedException CException + */ + public function testClientValidateAttributeThrowsExcpetion() + { + $model = $this->getModelMock(array( + 'operator' => '<=', + 'strict' => true, + 'compareAttribute' => 'bar', + )); + $validator = new CCompareValidator; + $validator->operator = '}'; + $validator->clientValidateAttribute($model, 'foo'); + } + + /** + * @expectedException CException + */ + public function testValidateThrowsExcpetionforBadOperator() + { + $model = $this->getModelMock(array( + 'operator' => ']]', + 'strict' => true, + 'compareAttribute' => 'bar', + )); + $model->validate(); + } + + /** + * Test overriding value by setting compareValue + * + * @return null + */ + public function testOverrideCompareValue() + { + $rules = array( + array('foo', 'compare', 'compareValue' => 'hello') + ); + + $stub = $this->getMock('ModelMock', array('rules')); + $stub->expects($this->any()) + ->method('rules') + ->will($this->returnValue($rules)); + + $stub->foo = 'foo'; + $this->assertFalse($stub->validate()); + + // client validation + $validator = new CCompareValidator; + $validator->operator = '='; + $validator->compareValue = 'bar'; + $script = $validator->clientValidateAttribute($stub, 'foo'); + $this->assertInternalType('string', $script); + $this->assertContains('Foo must be repeated exactly', $script); + } + + /** + * Mocks up an object to test with + * + * @param array $operator optional parameters to configure rule + * + * @return null + */ + protected function getModelMock($params=array()) + { + $rules = array( + array('foo', 'compare') + ); + + foreach ($params as $rule => $value) { + $rules[0][$rule] = $value; + } + + $stub = $this->getMock('ModelMock', array('rules')); + $stub->expects($this->any()) + ->method('rules') + ->will($this->returnValue($rules)); + + return $stub; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CDateValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CDateValidatorTest.php new file mode 100644 index 0000000..76d8f9d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CDateValidatorTest.php @@ -0,0 +1,91 @@ + + */ +class CDateValidatorTest extends CTestCase +{ + /** + * Test allow empty + * + * @return null + */ + public function testAllowEmptyOption() + { + $model = $this->getModelMock(array('allowEmpty' => true)); + $this->assertTrue($model->validate()); + + $model = $this->getModelMock(array('allowEmpty' => false)); + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('foo')); + } + + /** + * Test can validate different formats + * + * @return null + */ + public function testFormatOption() + { + // default format + $model = $this->getModelMock(); + $model->foo = '01/01/2011'; + $this->assertTrue($model->validate()); + $model->foo = '42/01/2011'; + $this->assertFalse($model->validate()); + + // custom format + $model = $this->getModelMock(array('format' => 'dd-MM-yyyy')); + $model->foo = '01-01-2011'; + $this->assertTrue($model->validate()); + $model->foo = '01-24-2011'; + $this->assertFalse($model->validate()); + + // array value, https://github.com/yiisoft/yii/issues/1955 + $model->foo = array('01-01-2011'); + $this->assertFalse($model->validate()); + } + + /** + * Test the timestamp option + * + * @return null + */ + public function testTimestampOption() + { + $model = $this->getModelMock(array('timestampAttribute' => 'bar')); + $model->foo = '01/01/2011'; + $this->assertTrue($model->validate()); + $this->assertInternalType('integer', $model->bar); + $this->assertEquals(strtotime('1 Jan 2011'), $model->bar); + } + + /** + * Mocks up an object to test with + * + * @param array $operator optional parameters to configure rule + * + * @return null + */ + protected function getModelMock($params=array()) + { + $rules = array( + array('foo', 'date') + ); + + foreach ($params as $rule => $value) { + $rules[0][$rule] = $value; + } + + $stub = $this->getMock('ModelMock', array('rules')); + $stub->expects($this->any()) + ->method('rules') + ->will($this->returnValue($rules)); + + return $stub; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CDefaultValueValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CDefaultValueValidatorTest.php new file mode 100644 index 0000000..8cf36f0 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CDefaultValueValidatorTest.php @@ -0,0 +1,66 @@ + + */ +class CDefaultValueValidatorTest extends CTestCase +{ + /** + * When value is empty|null, ensure a default value is set + * + * @return null + */ + public function testDefaultValueIsSetWhenSetOnEmptyIsTrue() + { + $model = $this->getModelMock(array('value' => 'foo')); + $this->assertTrue($model->validate()); + $this->assertEquals('foo', $model->foo); + + $model->foo = 'bar'; + $this->assertTrue($model->validate()); + $this->assertEquals('bar', $model->foo); + + } + + /** + * By setting setOnEmpty to false, the value will always be overriden + * + * @return null + */ + public function testDefaultValueIsSetWhenSetOnEmptyIsFalse() + { + $model = $this->getModelMock(array('value' => 'foo', 'setOnEmpty' => false)); + $model->foo = 'bar'; + $this->assertTrue($model->validate()); + $this->assertEquals('foo', $model->foo); + } + + /** + * Mocks up an object to test with + * + * @param array $operator optional parameters to configure rule + * + * @return null + */ + protected function getModelMock($params=array()) + { + $rules = array( + array('foo', 'default') + ); + + foreach ($params as $rule => $value) { + $rules[0][$rule] = $value; + } + + $stub = $this->getMock('ModelMock', array('rules')); + $stub->expects($this->any()) + ->method('rules') + ->will($this->returnValue($rules)); + + return $stub; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CEmailValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CEmailValidatorTest.php new file mode 100644 index 0000000..75dcf4c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CEmailValidatorTest.php @@ -0,0 +1,75 @@ +validate(array('email')); + $this->assertArrayHasKey('email', $model->getErrors()); + } + + public function testNumericEmail() + { + $emailValidator = new CEmailValidator(); + $result = $emailValidator->validateValue("5011@gmail.com"); + $this->assertTrue($result); + } + + public function providerIDNEmail() + { + return array( + // IDN validation enabled + array('test@президент.рф', true, true), + array('test@bücher.de', true, true), + array('test@检查域.cn', true, true), + array('☃-⌘@mañana.com', true, true), + array('test@google.com', true, true), + array('test@yiiframework.com', true, true), + array('bad-email', true, false), + array('without@tld', true, false), + array('without.at-mark.com', true, false), + array('检查域', true, false), + + // IDN validation disabled + array('test@президент.рф', false, false), + array('test@bücher.de', false, false), + array('test@检查域.cn', false, false), + array('☃-⌘@mañana.com', false, false), + array('test@google.com', false, true), + array('test@yiiframework.com', false, true), + array('bad-email', false, false), + array('without@tld', false, false), + array('without.at-mark.com', false, false), + array('检查域', false, false), + ); + } + + /** + * @dataProvider providerIDNEmail + * + * @param string $email + * @param boolean $validateIDN + * @param string $assertion + */ + public function testIDNUrl($email, $validateIDN, $assertion) + { + $emailValidator = new CEmailValidator(); + $emailValidator->validateIDN = $validateIDN; + $result = $emailValidator->validateValue($email); + $this->assertEquals($assertion, $result); + } + + /** + * https://github.com/yiisoft/yii/issues/1955 + */ + public function testArrayValue() + { + $model=new ValidatorTestModel('CEmailValidatorTest'); + $model->email=array('user@domain.tld'); + $model->validate(array('email')); + $this->assertTrue($model->hasErrors('email')); + $this->assertEquals(array('Email is not a valid email address.'),$model->getErrors('email')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CExistValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CExistValidatorTest.php new file mode 100644 index 0000000..d1f20ae --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CExistValidatorTest.php @@ -0,0 +1,142 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $columns = array( + 'id'=>'pk', + 'name'=>'string', + ); + $this->_connection->createCommand()->createTable($this->_tableName, $columns); + + CActiveRecord::$db=$this->_connection; + $this->declareArModelClass(); + } + + protected function tearDown() + { + $this->_connection->createCommand()->dropTable($this->_tableName); + $this->_connection->active=false; + } + + /** + * Declares test active record class. + * @return boolean success. + */ + protected function declareArModelClass() + { + if (!class_exists($this->_arModelName,false)) + { + $classDefinitionCode=<<_arModelName} extends CActiveRecord +{ + public static function model(\$className=__CLASS__) + { + return parent::model(\$className); + } + + public function tableName() + { + return '{$this->_tableName}'; + } + + public function rules() + { + return array( + array('name','exist','on'=>'simple'), + array('name','exist','caseSensitive'=>true,'on'=>'case_sensitive'), + array('name','exist','caseSensitive'=>false,'on'=>'not_case_sensitive'), + array('name','exist','criteria'=>array('alias'=>'test_alias'),'on'=>'criteria'), + ); + } +} +EOD; + eval($classDefinitionCode); + } + return true; + } + + public function testValidate() + { + $modelClassName = $this->_arModelName; + $name = 'test_name'; + + $model = new $modelClassName('simple'); + $model->name = $name; + $this->assertFalse($model->validate(),'Not existing value considered as valid!'); + + $model->save(false); + $this->assertTrue($model->validate(),'Existing value consider as invalid!'); + + $anotherModel = new $modelClassName('simple'); + $anotherModel->name = $name; + $this->assertTrue($anotherModel->validate(),'Duplicate entry of existing value considered as invalid!'); + } + + /** + * @depends testValidate + */ + public function testValidateCaseSensitive() + { + $modelClassName = $this->_arModelName; + $name = 'test_name'; + + $initModel = new $modelClassName(); + $initModel->name = $name; + $initModel->save(false); + + $caseSensitiveModel = new $modelClassName('case_sensitive'); + $caseSensitiveModel->name = $name; + $this->assertTrue($caseSensitiveModel->validate(),'Validation breaks in case sensitive mode!'); + $caseSensitiveModel->name = strtoupper($name); + $this->assertFalse($caseSensitiveModel->validate(),'Same value in other case considered as valid!'); + + $caseInsensitiveModel = new $modelClassName('not_case_sensitive'); + $caseInsensitiveModel->name = strtoupper($name); + $this->assertTrue($caseInsensitiveModel->validate(),'Same value in other case considered as invalid!'); + } + + /** + * @depends testValidate + */ + public function testValidateWithCriteria() + { + $modelClassName = $this->_arModelName; + $name = 'test_name'; + + $model = new $modelClassName('criteria'); + $model->name = $name; + $this->assertFalse($model->validate(),'Unable to validate model with custom criteria!'); + } + + /** + * https://github.com/yiisoft/yii/issues/1955 + */ + public function testArrayValue() + { + $modelClassName = $this->_arModelName; + $model = new $modelClassName('simple'); + $model->name = array('test_name'); + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('name')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CFileValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CFileValidatorTest.php new file mode 100644 index 0000000..06c1ec8 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CFileValidatorTest.php @@ -0,0 +1,38 @@ +assertEquals($assertion, $fileValidator->sizeToBytes($sizeString)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CNumberValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CNumberValidatorTest.php new file mode 100644 index 0000000..f94c7b4 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CNumberValidatorTest.php @@ -0,0 +1,43 @@ + array('Number must be a number.'))), + array(true, array('number' => array('Number must be a number.'))), + // integer + array(20, array('number' => array('Number is too big (maximum is 15).'))), + array(1, array('number' => array('Number is too small (minimum is 5).'))), + // float + array(20.5, array('number' => array('Number must be an integer.','Number is too big (maximum is 15).'))), + array(1.5, array('number' => array('Number must be an integer.','Number is too small (minimum is 5).'))), + // string + array('20', array('number' => array('Number is too big (maximum is 15).'))), + array('20.5', array('number' => array('Number must be an integer.','Number is too big (maximum is 15).'))), + array('1', array('number' => array('Number is too small (minimum is 5).'))), + array('1.5', array('number' => array('Number must be an integer.','Number is too small (minimum is 5).'))), + array('abc', array('number' => array('Number must be a number.'))), + array('a100', array('number' => array('Number must be a number.'))), + // array + array(array(1,2), array('number' => array('Number must be a number.'))), + // object + array((object)array('a'=>1,'b'=>2), array('number' => array('Number must be a number.'))), + ); + } + + /** + * https://github.com/yiisoft/yii/issues/1669 + * @dataProvider providerIssue1669 + */ + public function testIssue1669($value, $assertion) + { + $model = new ValidatorTestModel('CNumberValidatorTest'); + $model->number = $value; + $model->validate(array('number')); + $this->assertSame($assertion, $model->getErrors()); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CRangeValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CRangeValidatorTest.php new file mode 100644 index 0000000..09773f6 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CRangeValidatorTest.php @@ -0,0 +1,35 @@ +string1 = ''; + $model->string2 = ''; + $model->validate(array('string1','string2')); + $this->assertArrayHasKey('string1', $model->getErrors()); + $this->assertArrayNotHasKey('string2', $model->getErrors()); + } + + public function testZeroString() + { + $model = new ValidatorTestModel('CRangeValidatorTest'); + $model->string1 = '0'; + $model->string2 = '0'; + $model->validate(array('string1','string2')); + $this->assertArrayNotHasKey('string1', $model->getErrors()); + $this->assertArrayHasKey('string2', $model->getErrors()); + } + + public function testZeroNumber() + { + $model = new ValidatorTestModel('CRangeValidatorTest'); + $model->string1 = 0; + $model->string2 = 0; + $model->validate(array('string1','string2')); + $this->assertArrayNotHasKey('string1', $model->getErrors()); + $this->assertArrayHasKey('string2', $model->getErrors()); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CRequiredValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CRequiredValidatorTest.php new file mode 100644 index 0000000..15b8140 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CRequiredValidatorTest.php @@ -0,0 +1,29 @@ +validate(array('username')); + $this->assertArrayHasKey('username', $model->getErrors()); + } + + public function testSpaces() + { + $model = new ValidatorTestModel('CRequiredValidatorTest'); + $model->username = ' '; + $model->validate(array('username')); + $this->assertArrayNotHasKey('username', $model->getErrors()); + } + + public function testEmptyWithSpaces() + { + $model = new ValidatorTestModel('CRequiredValidatorTest'); + $model->address = ' '; + $model->validate(array('address')); + $this->assertArrayHasKey('address', $model->getErrors()); + } + +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CStringValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CStringValidatorTest.php new file mode 100644 index 0000000..e8517b8 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CStringValidatorTest.php @@ -0,0 +1,98 @@ +validate(array('string1')); + $this->assertTrue($model1->hasErrors('string1')); + $this->assertSame(array('Too short message.'),$model1->getErrors('string1')); + + // 9 characters length value + $model2=new ValidatorTestModel('CStringValidatorTest'); + $model2->string1='123456789'; + $model2->validate(array('string1')); + $this->assertTrue($model2->hasErrors('string1')); + $this->assertSame(array('Too short message.'),$model2->getErrors('string1')); + + // 10 characters length value + $model3=new ValidatorTestModel('CStringValidatorTest'); + $model3->string1='1234567890'; + $model3->validate(array('string1')); + $this->assertFalse($model3->hasErrors('string1')); + $this->assertNotSame(array('Too short message.'),$model3->getErrors('string1')); + + // array value: https://github.com/yiisoft/yii/issues/1955 + $model4=new ValidatorTestModel('CStringValidatorTest'); + $model4->string1=array('1234567890'); + $model4->validate(array('string1')); + $this->assertTrue($model4->hasErrors('string1')); + } + + public function testMax() + { + // null value + $model1=new ValidatorTestModel('CStringValidatorTest'); + $model1->validate(array('string2')); + $this->assertFalse($model1->hasErrors('string2')); + $this->assertNotSame(array('Too long message.'),$model1->getErrors('string2')); + + // 11 characters length value + $model2=new ValidatorTestModel('CStringValidatorTest'); + $model2->string2='12345678901'; + $model2->validate(array('string2')); + $this->assertTrue($model2->hasErrors('string2')); + $this->assertSame(array('Too long message.'),$model2->getErrors('string2')); + + // 10 characters length value + $model3=new ValidatorTestModel('CStringValidatorTest'); + $model3->string2='1234567890'; + $model3->validate(array('string2')); + $this->assertFalse($model3->hasErrors('string2')); + $this->assertNotSame(array('Too long message.'),$model3->getErrors('string2')); + + // array value: https://github.com/yiisoft/yii/issues/1955 + $model4=new ValidatorTestModel('CStringValidatorTest'); + $model4->string2=array('1234567890'); + $model4->validate(array('string2')); + $this->assertTrue($model4->hasErrors('string2')); + } + + public function testIs() + { + // null value + $model1=new ValidatorTestModel('CStringValidatorTest'); + $model1->validate(array('string3')); + $this->assertTrue($model1->hasErrors('string3')); + $this->assertSame(array('Error message.'),$model1->getErrors('string3')); + + // 9 characters length value + $model2=new ValidatorTestModel('CStringValidatorTest'); + $model2->string3='123456789'; + $model2->validate(array('string3')); + $this->assertTrue($model2->hasErrors('string3')); + $this->assertSame(array('Error message.'),$model2->getErrors('string3')); + + // 11 characters length value + $model3=new ValidatorTestModel('CStringValidatorTest'); + $model3->string3='12345678901'; + $model3->validate(array('string3')); + $this->assertTrue($model3->hasErrors('string3')); + $this->assertSame(array('Error message.'),$model3->getErrors('string3')); + + // 10 characters length value + $model4=new ValidatorTestModel('CStringValidatorTest'); + $model4->string3='1234567890'; + $model4->validate(array('string3')); + $this->assertFalse($model4->hasErrors('string3')); + $this->assertNotSame(array('Error message.'),$model4->getErrors('string3')); + + // array value: https://github.com/yiisoft/yii/issues/1955 + $model5=new ValidatorTestModel('CStringValidatorTest'); + $model5->string3=array('1234567890'); + $model5->validate(array('string3')); + $this->assertTrue($model5->hasErrors('string3')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CTypeValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CTypeValidatorTest.php new file mode 100644 index 0000000..a239823 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CTypeValidatorTest.php @@ -0,0 +1,153 @@ +type='integer'; + $this->assertTrue($validator->validateValue(42)); + $this->assertTrue($validator->validateValue(+42)); + $this->assertTrue($validator->validateValue(-42)); + $this->assertTrue($validator->validateValue('42')); + $this->assertTrue($validator->validateValue('+42')); + $this->assertTrue($validator->validateValue('-42')); + $this->assertFalse($validator->validateValue('42 is a good number!')); + $this->assertFalse($validator->validateValue(3.1415926)); + $this->assertFalse($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } + + public function testIntegerStrict() + { + $validator=new CTypeValidator(); + $validator->type='integer'; + $validator->strict=true; + $this->assertTrue($validator->validateValue(42)); + $this->assertTrue($validator->validateValue(+42)); + $this->assertTrue($validator->validateValue(-42)); + $this->assertFalse($validator->validateValue('42')); + $this->assertFalse($validator->validateValue('+42')); + $this->assertFalse($validator->validateValue('-42')); + $this->assertFalse($validator->validateValue('42 is a good number!')); + $this->assertFalse($validator->validateValue(3.1415926)); + $this->assertFalse($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } + + public function testFloat() + { + $validator=new CTypeValidator(); + $validator->type='float'; + $this->assertTrue($validator->validateValue(42)); + $this->assertTrue($validator->validateValue(42.0)); + $this->assertTrue($validator->validateValue(+42.1)); + $this->assertTrue($validator->validateValue(-42.2)); + $this->assertTrue($validator->validateValue('42')); + $this->assertTrue($validator->validateValue('42.1')); + $this->assertTrue($validator->validateValue('+42.2')); + $this->assertTrue($validator->validateValue('-42.3')); + $this->assertFalse($validator->validateValue('42.3 is a good number!')); + $this->assertFalse($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } + + public function testFloatStrict() + { + $validator=new CTypeValidator(); + $validator->type='float'; + $validator->strict=true; + $this->assertFalse($validator->validateValue(42)); + $this->assertTrue($validator->validateValue(42.0)); + $this->assertTrue($validator->validateValue(+42.1)); + $this->assertTrue($validator->validateValue(-42.2)); + $this->assertFalse($validator->validateValue('42')); + $this->assertFalse($validator->validateValue('42.1')); + $this->assertFalse($validator->validateValue('+42.2')); + $this->assertFalse($validator->validateValue('-42.3')); + $this->assertFalse($validator->validateValue('42.3 is a good number!')); + $this->assertFalse($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } + + public function testString() + { + $validator=new CTypeValidator(); + $validator->type='string'; + $this->assertFalse($validator->validateValue(42)); + $this->assertFalse($validator->validateValue(42.0)); + $this->assertTrue($validator->validateValue('42')); + $this->assertTrue($validator->validateValue('42.3 is a good number!')); + $this->assertFalse($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } + + public function testArray() + { + $validator=new CTypeValidator(); + $validator->type='array'; + $this->assertFalse($validator->validateValue(42)); + $this->assertFalse($validator->validateValue(42.0)); + $this->assertFalse($validator->validateValue('42.3 is a good number!')); + $this->assertTrue($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } + + // TODO: the following three should be tested for actual pattern matching + + public function testDate() + { + $validator=new CTypeValidator(); + $validator->type='date'; + $this->assertFalse($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(42)); + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } + + public function testTime() + { + $validator=new CTypeValidator(); + $validator->type='time'; + $this->assertFalse($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(42)); + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } + + public function testDateTime() + { + $validator=new CTypeValidator(); + $validator->type='datetime'; + $this->assertFalse($validator->validateValue(array(13))); + + $this->assertFalse($validator->validateValue(42)); + $this->assertFalse($validator->validateValue(true)); + $this->assertFalse($validator->validateValue(false)); + $this->assertFalse($validator->validateValue(new stdClass())); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CUniqueValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CUniqueValidatorTest.php new file mode 100644 index 0000000..6afd20f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CUniqueValidatorTest.php @@ -0,0 +1,142 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $columns = array( + 'id'=>'pk', + 'name'=>'string', + ); + $this->_connection->createCommand()->createTable($this->_tableName, $columns); + + CActiveRecord::$db=$this->_connection; + $this->declareArModelClass(); + } + + protected function tearDown() + { + $this->_connection->createCommand()->dropTable($this->_tableName); + $this->_connection->active=false; + } + + /** + * Declares test active record class. + * @return boolean success. + */ + protected function declareArModelClass() + { + if (!class_exists($this->_arModelName,false)) + { + $classDefinitionCode=<<_arModelName} extends CActiveRecord +{ + public static function model(\$className=__CLASS__) + { + return parent::model(\$className); + } + + public function tableName() + { + return '{$this->_tableName}'; + } + + public function rules() + { + return array( + array('name','unique','on'=>'simple'), + array('name','unique','caseSensitive'=>true,'on'=>'case_sensitive'), + array('name','unique','caseSensitive'=>false,'on'=>'not_case_sensitive'), + array('name','unique','criteria'=>array('alias'=>'test_alias'),'on'=>'criteria'), + ); + } +} +EOD; + eval($classDefinitionCode); + } + return true; + } + + public function testValidate() + { + $modelClassName = $this->_arModelName; + $name = 'test_name'; + + $model = new $modelClassName('simple'); + $model->name = $name; + $this->assertTrue($model->validate(),'Unique value considered as invalid!'); + + $model->save(false); + $this->assertTrue($model->validate(),'Unique value keeper considered as invalid!'); + + $anotherModel = new $modelClassName('simple'); + $anotherModel->name = $name; + $this->assertFalse($anotherModel->validate(),'Duplicate entry of unique value considered as valid!'); + } + + /** + * @depends testValidate + */ + public function testValidateCaseSensitive() + { + $modelClassName = $this->_arModelName; + $name = 'test_name'; + + $initModel = new $modelClassName(); + $initModel->name = $name; + $initModel->save(false); + + $caseSensitiveModel = new $modelClassName('case_sensitive'); + $caseSensitiveModel->name = $name; + $this->assertFalse($caseSensitiveModel->validate(),'Validation breaks in case sensitive mode!'); + $caseSensitiveModel->name = strtoupper($name); + $this->assertTrue($caseSensitiveModel->validate(),'Same value in other case considered as invalid!'); + + $caseInsensitiveModel = new $modelClassName('not_case_sensitive'); + $caseInsensitiveModel->name = strtoupper($name); + $this->assertFalse($caseInsensitiveModel->validate(),'Same value in other case considered as valid!'); + } + + /** + * @depends testValidate + */ + public function testValidateWithCriteria() + { + $modelClassName = $this->_arModelName; + $name = 'test_name'; + + $model = new $modelClassName('criteria'); + $model->name = $name; + $this->assertTrue($model->validate(),'Unable to validate model with custom criteria!'); + } + + /** + * https://github.com/yiisoft/yii/issues/1955 + */ + public function testArrayValue() + { + $modelClassName = $this->_arModelName; + $model = new $modelClassName('simple'); + $model->name = array('test_name'); + $this->assertFalse($model->validate()); + $this->assertTrue($model->hasErrors('name')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CUrlValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CUrlValidatorTest.php new file mode 100644 index 0000000..65272b9 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CUrlValidatorTest.php @@ -0,0 +1,188 @@ +validate(array('url')); + $this->assertArrayHasKey('url', $model->getErrors()); + } + + public function testArbitraryUrl() + { + $urlValidator = new CUrlValidator(); + $url = 'http://testing-arbitrary-domain.com/'; + $result = $urlValidator->validateValue($url); + $this->assertEquals($url, $result); + } + + public function providerIDNUrl() + { + return array( + // IDN validation enabled + array('http://президент.рф/', true, 'http://президент.рф/'), + array('http://bücher.de/?get=param', true, 'http://bücher.de/?get=param'), + array('http://检查域.cn/', true, 'http://检查域.cn/'), + array('http://mañana.com/', true, 'http://mañana.com/'), + array('http://☃-⌘.com/', true, 'http://☃-⌘.com/'), + array('http://google.com/', true, 'http://google.com/'), + array('http://www.yiiframework.com/forum/', true, 'http://www.yiiframework.com/forum/'), + array('https://www.yiiframework.com/extensions/', true, 'https://www.yiiframework.com/extensions/'), + array('ftp://www.yiiframework.com/', true, false), + array('www.yiiframework.com', true, false), + + // IDN validation disabled + array('http://президент.рф/', false, false), + array('http://bücher.de/?get=param', false, false), + array('http://检查域.cn/', false, false), + array('http://mañana.com/', false, false), + array('http://☃-⌘.com/', false, false), + array('http://google.com/', false, 'http://google.com/'), + array('http://www.yiiframework.com/forum/', false, 'http://www.yiiframework.com/forum/'), + array('https://www.yiiframework.com/extensions/', false, 'https://www.yiiframework.com/extensions/'), + array('ftp://www.yiiframework.com/', false, false), + array('www.yiiframework.com', false, false), + ); + } + + /** + * @dataProvider providerIDNUrl + * + * @param string $url + * @param boolean $validateIDN + * @param string $assertion + */ + public function testIDNUrl($url, $validateIDN, $assertion) + { + $urlValidator = new CUrlValidator(); + $urlValidator->validateIDN = $validateIDN; + $result = $urlValidator->validateValue($url); + $this->assertEquals($assertion, $result); + } + + public function providerValidSchemes() + { + return array( + array('ftp://yiiframework.com/', array('ftp', 'http', 'https'), 'ftp://yiiframework.com/'), + array('ftp://yiiframework.com/', array('http', 'https'), false), + array('ftp://yiiframework.com/', array('ftp'), 'ftp://yiiframework.com/'), + + array('that-s-not-an-url-at-all', array('ftp', 'http', 'https'), false), + array('that-s-not-an-url-at-all', array(), false), + array('ftp://that-s-not-an-url-at-all', array('ftp'), false), + + array('http://☹.com/', array('ftp'), false), + array('http://☹.com/', array('rsync'), false), + array('http://☹.com/', array('http', 'https'), false), + + array('rsync://gentoo.org:873/distfiles/', array('rsync', 'http', 'https'), 'rsync://gentoo.org:873/distfiles/'), + array('rsync://gentoo.org:873/distfiles/', array('http', 'https'), false), + array('rsync://gentoo.org:873/distfiles/', array('rsync'), 'rsync://gentoo.org:873/distfiles/'), + ); + } + + /** + * @dataProvider providerValidSchemes + * + * @param string $url + * @param array $validSchemes + * @param string $assertion + */ + public function testValidSchemes($url, $validSchemes, $assertion) + { + $urlValidator = new CUrlValidator(); + $urlValidator->validSchemes = $validSchemes; + $result = $urlValidator->validateValue($url); + $this->assertEquals($assertion, $result); + } + + public function providerDefaultScheme() + { + return array( + array('https://yiiframework.com/?get=param', null, 'https://yiiframework.com/?get=param'), + array('ftp://yiiframework.com/?get=param', null, false), + array('yiiframework.com/?get=param', null, false), + array('that-s-not-an-url-at-all', null, false), + + array('https://yiiframework.com/?get=param', 'http', 'https://yiiframework.com/?get=param'), + array('ftp://yiiframework.com/?get=param', 'http', false), + array('yiiframework.com/?get=param', 'http', 'http://yiiframework.com/?get=param'), + array('that-s-not-an-url-at-all', 'http', false), + + array('https://yiiframework.com/?get=param', 'ftp', 'https://yiiframework.com/?get=param'), + array('ftp://yiiframework.com/?get=param', 'ftp', false), + array('yiiframework.com/?get=param', 'ftp', false), + array('that-s-not-an-url-at-all', 'ftp', false), + ); + } + + /** + * @dataProvider providerDefaultScheme + * + * @param string $url + * @param array $defaultScheme + * @param string $assertion + */ + public function testDefaultScheme($url, $defaultScheme, $assertion) + { + $urlValidator = new CUrlValidator(); + $urlValidator->defaultScheme = $defaultScheme; + $result = $urlValidator->validateValue($url); + $this->assertEquals($assertion, $result); + } + + + public function providerAllowEmpty() + { + return array( + array('https://yiiframework.com/?get=param', false, 'https://yiiframework.com/?get=param'), + array('ftp://yiiframework.com/?get=param', false, false), + array('yiiframework.com/?get=param', false, false), + array('that-s-not-an-url-at-all', false, false), + array('http://☹.com/', false, false), + array('rsync://gentoo.org:873/distfiles/', false, false), + array('https://gentoo.org:8080/distfiles/', false, 'https://gentoo.org:8080/distfiles/'), + array(' ', false, false), + array('', false, false), + + array('https://yiiframework.com/?get=param', true, 'https://yiiframework.com/?get=param'), + array('ftp://yiiframework.com/?get=param', true, false), + array('yiiframework.com/?get=param', true, false), + array('that-s-not-an-url-at-all', true, false), + array('http://☹.com/', true, false), + array('rsync://gentoo.org:873/distfiles/', true, false), + array('https://gentoo.org:8080/distfiles/', true, 'https://gentoo.org:8080/distfiles/'), + array(' ', true, false), + array('', true, ''), + ); + } + + /** + * @dataProvider providerAllowEmpty + * + * @param string $url + * @param array $allowEmpty + * @param string $assertion + */ + public function testAllowEmpty($url, $allowEmpty, $assertion) + { + $urlValidator = new CUrlValidator(); + $urlValidator->allowEmpty = $allowEmpty; + $result = $urlValidator->validateValue($url); + $this->assertEquals($assertion, $result); + } + + /** + * https://github.com/yiisoft/yii/issues/1955 + */ + public function testArrayValue() + { + $model=new ValidatorTestModel('CUrlValidatorTest'); + $model->url=array('http://yiiframework.com/'); + $model->validate(array('url')); + $this->assertTrue($model->hasErrors('url')); + $this->assertEquals(array('Url is not a valid URL.'),$model->getErrors('url')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CValidatorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CValidatorTest.php new file mode 100644 index 0000000..e1d819c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/CValidatorTest.php @@ -0,0 +1,66 @@ +validate(); + + $errors=$scenario1TestModel->getErrors(); + $this->assertEquals(6, count($errors)); + $this->assertArrayHasKey('title', $errors); + $this->assertArrayHasKey('firstName', $errors); + $this->assertArrayHasKey('lastName', $errors); + $this->assertArrayHasKey('nickName', $errors); + $this->assertArrayHasKey('patronymic', $errors); + $this->assertArrayHasKey('login', $errors); + + + // scenario2 + // fields should be validated: firstName, lastName, patronymic, login, birthday + $scenario2TestModel=new ScenariosTestModel('scenario2'); + $scenario2TestModel->validate(); + + $errors=$scenario2TestModel->getErrors(); + $this->assertEquals(5, count($errors)); + $this->assertArrayHasKey('firstName', $errors); + $this->assertArrayHasKey('lastName', $errors); + $this->assertArrayHasKey('patronymic', $errors); + $this->assertArrayHasKey('login', $errors); + $this->assertArrayHasKey('birthday', $errors); + + + // scenario3 + // fields should be validated: lastName, patronymic, nickName, login + $scenario3TestModel=new ScenariosTestModel('scenario3'); + $scenario3TestModel->validate(); + + $errors=$scenario3TestModel->getErrors(); + $this->assertEquals(4, count($errors)); + $this->assertArrayHasKey('lastName', $errors); + $this->assertArrayHasKey('patronymic', $errors); + $this->assertArrayHasKey('nickName', $errors); + $this->assertArrayHasKey('login', $errors); + + + // scenario4 + // fields should be validated: login + $scenario4TestModel=new ScenariosTestModel('scenario4'); + $scenario4TestModel->validate(); + + $errors=$scenario4TestModel->getErrors(); + $this->assertEquals(1, count($errors)); + $this->assertArrayHasKey('login', $errors); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ModelMock.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ModelMock.php new file mode 100644 index 0000000..df07aec --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ModelMock.php @@ -0,0 +1,8 @@ +'scenario1'), + + // scenario1 and scenario2 + array('firstName', 'required', 'except'=>'scenario3, scenario4'), + + // scenario1, scenario2 and scenario3 + array('lastName', 'required', 'on'=>array('scenario1', 'scenario2', 'scenario3')), + + // scenario1, scenario2 and scenario3 + array('patronymic', 'required', 'except'=>array('scenario4')), + + // scenario1 and scenario3 + array('nickName', 'required', 'on'=>array('scenario1', 'scenario2', 'scenario3'), 'except'=>'scenario2'), + + // scenario1, scenario2, scenario3 and scenario4 + array('login', 'required'), + + // useless rule + array('password', 'required', 'on'=>'scenario1,scenario2,scenario3,scenario4', + 'except'=>array('scenario1', 'scenario2', 'scenario3', 'scenario4')), + + // scenario2 + array('birthday', 'required', 'on'=>'scenario2', 'except'=>'scenario3'), + ); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ValidatorTestModel.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ValidatorTestModel.php new file mode 100644 index 0000000..78f79f7 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/validators/ValidatorTestModel.php @@ -0,0 +1,40 @@ +10, 'tooShort'=>'Too short message.', 'allowEmpty'=>false, + 'on'=>'CStringValidatorTest'), + array('string2', 'length', 'max'=>10, 'tooLong'=>'Too long message.', 'allowEmpty'=>false, + 'on'=>'CStringValidatorTest'), + array('string3', 'length', 'is'=>10, 'message'=>'Error message.', 'allowEmpty'=>false, + 'on'=>'CStringValidatorTest'), + + array('email', 'email', 'allowEmpty'=>false, 'on'=>'CEmailValidatorTest'), + + array('url', 'url', 'allowEmpty'=>false, 'on'=>'CUrlValidatorTest'), + + array('number', 'numerical', 'min'=>5, 'max'=>15, 'integerOnly'=>true, 'on'=>'CNumberValidatorTest'), + + array('username', 'required', 'trim' => false, 'on' => 'CRequiredValidatorTest'), + array('address', 'required', 'on' => 'CRequiredValidatorTest'), + + array('string1', 'in', 'allowEmpty' => false, 'range' => array(0,1,7,13), 'on' => 'CRangeValidatorTest'), + array('string2', 'in', 'allowEmpty' => false, 'range' => array('',1,7,13), 'on' => 'CRangeValidatorTest'), + ); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CActiveDataProviderTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CActiveDataProviderTest.php new file mode 100644 index 0000000..d0e966c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CActiveDataProviderTest.php @@ -0,0 +1,58 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->db=new CDbConnection('sqlite::memory:'); + $this->db->active=true; + $this->db->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/../db/data/sqlite.sql')); + CActiveRecord::$db=$this->db; + } + + public function tearDown() + { + $this->db->active=false; + } + + public function testCountCriteria() + { + // 1 + $dataProvider=new CActiveDataProvider('Post',array( + 'criteria'=>array( + 'condition'=>'content LIKE "%content%"', + 'order'=>'create_time DESC', + 'with'=>array('author'), + ), + 'pagination'=>array( + 'pageSize'=>5, + ), + )); + $this->assertSame($dataProvider->countCriteria,$dataProvider->criteria); + $this->assertEquals(5,$dataProvider->getTotalItemCount(true)); + + // 2 + $dataProvider->setCountCriteria(array( + 'condition'=>'content LIKE "%content 1%"', + )); + $this->assertNotSame($dataProvider->countCriteria,$dataProvider->criteria); + $this->assertEquals(1,$dataProvider->getTotalItemCount(true)); + + // 3 + $dataProvider->setCountCriteria(array( + 'condition'=>'content LIKE "%content%"', + )); + $this->assertNotSame($dataProvider->countCriteria,$dataProvider->criteria); + $this->assertEquals(5,$dataProvider->getTotalItemCount(true)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CArrayDataProviderTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CArrayDataProviderTest.php new file mode 100644 index 0000000..f230ccf --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CArrayDataProviderTest.php @@ -0,0 +1,205 @@ +assertEquals($simpleArray, $dataProvider->getData()); + } + + public function testGetSortedData() + { + $simpleArray = array(array('sortField' => 1), array('sortField' => 0)); + $dataProvider = new CArrayDataProvider( + $simpleArray, + array( + 'sort' => array( + 'attributes' => array( + 'sort' => array( + 'asc' => 'sortField ASC', + 'desc' => 'sortField DESC', + 'label' => 'Sorting', + 'default' => 'asc', + ), + ), + 'defaultOrder' => array( + 'sort' => CSort::SORT_ASC, + ) + ), + ) + ); + $sortedArray = array(array('sortField' => 0), array('sortField' => 1)); + $this->assertEquals($sortedArray, $dataProvider->getData()); + } + + public function testGetSortedDataByInnerArrayField() + { + $simpleArray = array( + array('innerArray' => array('sortField' => 1)), + array('innerArray' => array('sortField' => 0)) + ); + $dataProvider = new CArrayDataProvider( + $simpleArray, + array( + 'sort' => array( + 'attributes' => array( + 'sort' => array( + 'asc' => 'innerArray.sortField ASC', + 'desc' => 'innerArray.sortField DESC', + 'label' => 'Sorting', + 'default' => 'asc', + ), + ), + 'defaultOrder' => array( + 'sort' => CSort::SORT_ASC, + ) + ), + ) + ); + $sortedArray = array( + array('innerArray' => array('sortField' => 0)), + array('innerArray' => array('sortField' => 1)) + ); + $this->assertEquals($sortedArray, $dataProvider->getData()); + } + + public function testCaseSensitiveSort() + { + // source data + $unsortedProjects=array( + array('title'=>'Zabbix', 'license'=>'GPL'), + array('title'=>'munin', 'license'=>'GPL'), + array('title'=>'Arch Linux', 'license'=>'GPL'), + array('title'=>'Nagios', 'license'=>'GPL'), + array('title'=>'zend framework', 'license'=>'BSD'), + array('title'=>'Zope', 'license'=>'ZPL'), + array('title'=>'active-record', 'license'=>false), + array('title'=>'ActiveState', 'license'=>false), + array('title'=>'mach', 'license'=>false), + array('title'=>'MySQL', 'license'=>'GPL'), + array('title'=>'mssql', 'license'=>'EULA'), + array('title'=>'Master-Master', 'license'=>false), + array('title'=>'Zend Engine', 'license'=>false), + array('title'=>'Mageia Linux', 'license'=>'GNU GPL'), + array('title'=>'nginx', 'license'=>'BSD'), + array('title'=>'Mozilla Firefox', 'license'=>'MPL'), + ); + + // expected data + $sortedProjects=array( + // upper cased titles + array('title'=>'ActiveState', 'license'=>false), + array('title'=>'Arch Linux', 'license'=>'GPL'), + array('title'=>'Mageia Linux', 'license'=>'GNU GPL'), + array('title'=>'Master-Master', 'license'=>false), + array('title'=>'Mozilla Firefox', 'license'=>'MPL'), + array('title'=>'MySQL', 'license'=>'GPL'), + array('title'=>'Nagios', 'license'=>'GPL'), + array('title'=>'Zabbix', 'license'=>'GPL'), + array('title'=>'Zend Engine', 'license'=>false), + array('title'=>'Zope', 'license'=>'ZPL'), + // lower cased titles + array('title'=>'active-record', 'license'=>false), + array('title'=>'mach', 'license'=>false), + array('title'=>'mssql', 'license'=>'EULA'), + array('title'=>'munin', 'license'=>'GPL'), + array('title'=>'nginx', 'license'=>'BSD'), + array('title'=>'zend framework', 'license'=>'BSD'), + ); + + $dataProvider=new CArrayDataProvider($unsortedProjects, array( + 'sort'=>array( + 'attributes'=>array( + 'sort'=>array( + 'asc'=>'title ASC', + 'desc'=>'title DESC', + 'label'=>'Title', + 'default'=>'desc', + ), + ), + 'defaultOrder'=>array( + 'sort'=>CSort::SORT_ASC, + ) + ), + 'pagination'=>array( + 'pageSize'=>100500, + ), + )); + + // $dataProvider->caseSensitiveSort is true by default, so we do not touching it + + $this->assertEquals($sortedProjects, $dataProvider->getData()); + } + + public function testCaseInsensitiveSort() + { + // source data + $unsortedProjects=array( + array('title'=>'Zabbix', 'license'=>'GPL'), + array('title'=>'munin', 'license'=>'GPL'), + array('title'=>'Arch Linux', 'license'=>'GPL'), + array('title'=>'Nagios', 'license'=>'GPL'), + array('title'=>'zend framework', 'license'=>'BSD'), + array('title'=>'Zope', 'license'=>'ZPL'), + array('title'=>'active-record', 'license'=>false), + array('title'=>'ActiveState', 'license'=>false), + array('title'=>'mach', 'license'=>false), + array('title'=>'MySQL', 'license'=>'GPL'), + array('title'=>'mssql', 'license'=>'EULA'), + array('title'=>'Master-Master', 'license'=>false), + array('title'=>'Zend Engine', 'license'=>false), + array('title'=>'Mageia Linux', 'license'=>'GNU GPL'), + array('title'=>'nginx', 'license'=>'BSD'), + array('title'=>'Mozilla Firefox', 'license'=>'MPL'), + ); + + // expected data + $sortedProjects=array( + // case is not taken into account + array('title'=>'active-record', 'license'=>false), + array('title'=>'ActiveState', 'license'=>false), + array('title'=>'Arch Linux', 'license'=>'GPL'), + array('title'=>'mach', 'license'=>false), + array('title'=>'Mageia Linux', 'license'=>'GNU GPL'), + array('title'=>'Master-Master', 'license'=>false), + array('title'=>'Mozilla Firefox', 'license'=>'MPL'), + array('title'=>'mssql', 'license'=>'EULA'), + array('title'=>'munin', 'license'=>'GPL'), + array('title'=>'MySQL', 'license'=>'GPL'), + array('title'=>'Nagios', 'license'=>'GPL'), + array('title'=>'nginx', 'license'=>'BSD'), + array('title'=>'Zabbix', 'license'=>'GPL'), + array('title'=>'Zend Engine', 'license'=>false), + array('title'=>'zend framework', 'license'=>'BSD'), + array('title'=>'Zope', 'license'=>'ZPL'), + ); + + $dataProvider=new CArrayDataProvider($unsortedProjects, array( + 'sort'=>array( + 'attributes'=>array( + 'sort'=>array( + 'asc'=>'title ASC', + 'desc'=>'title DESC', + 'label'=>'Title', + 'default'=>'desc', + ), + ), + 'defaultOrder'=>array( + 'sort'=>CSort::SORT_ASC, + ) + ), + 'pagination'=>array( + 'pageSize'=>100500, + ), + )); + + // we're explicitly setting case insensitive sort + $dataProvider->caseSensitiveSort = false; + + $this->assertEquals($sortedProjects, $dataProvider->getData()); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CAssetManagerTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CAssetManagerTest.php new file mode 100644 index 0000000..50a83a2 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CAssetManagerTest.php @@ -0,0 +1,42 @@ +reset(); + $am2->init($app); + $this->assertEquals($am2->basePath,$app->basePath.DIRECTORY_SEPARATOR.'assets'); + } + + public function testBaseUrl() + { + $app=new TestApplication; + $app->request->baseUrl='/test'; + $am=new CAssetManager; + $am->init($app); + $this->assertEquals($am->baseUrl,'/test/assets'); + } + + public function testPublishFile() + { + $app=new TestApplication; + $app->reset(); + $am=new CAssetManager; + $am->init($app); + $path1=$am->getPublishedPath(__FILE__); + clearstatcache(); + $this->assertFalse(is_file($path1)); + $url=$am->publish(__FILE__); + $path2=$am->getPublishedPath(__FILE__); + $this->assertEquals($path1,$path2); + clearstatcache(); + $this->assertTrue(is_file($path1)); + $this->assertEquals(basename($path1),basename(__FILE__)); + $this->assertEquals($url,$am->baseUrl.'/'.basename(dirname($path2)).'/'.basename($path2)); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CClientScriptTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CClientScriptTest.php new file mode 100644 index 0000000..f4ab14e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CClientScriptTest.php @@ -0,0 +1,419 @@ +_clientScript = new CClientScript(); + $this->_clientScript->setCoreScriptUrl("assets/12345"); + $this->_clientScript->registerCoreScript('jquery'); + $this->_clientScript->registerCoreScript('yii'); + } + + /* Test Script Getters */ + + public function testGetCoreScriptUrl() + { + $this->assertEquals('assets/12345', $this->_clientScript->getCoreScriptUrl()); + } + + + public function providerGetPackageBaseUrl() + { + return array( + array('jquery', 'assets/12345'), + array('yii', 'assets/12345') + ); + } + + /** + * @dataProvider providerGetPackageBaseUrl + * + * @param string $name + * @param string $assertion + */ + public function testGetPackageBaseUrl($name, $assertion) + { + $this->assertEquals($assertion,$this->_clientScript->getPackageBaseUrl($name)); + } + + /* Test Script Registers */ + + public function providerCoreScripts() + { + return array( + array('jquery', array('js'=>array('jquery.js'))), + array('yiitab', array('js'=>array('jquery.yiitab.js'), 'depends'=>array('jquery'))), + array('yiiactiveform', array('js'=>array('jquery.yiiactiveform.js'), 'depends'=>array('jquery'))) + + ); + } + /** + * @dataProvider providerCoreScripts + * + * @param string $name + * @param array $assertion + */ + public function testRegisterCoreScript($name, $assertion) + { + $returnedClientScript = $this->_clientScript->registerCoreScript($name); + $this->assertEquals($assertion, $returnedClientScript->corePackages[$name]); + } + + /** + * @dataProvider providerCoreScripts + * + * @param string $name + * @param array $assertion + */ + public function testRegisterPackage($name, $assertion) + { + $returnedClientScript = $this->_clientScript->registerPackage($name); + $this->assertEquals($assertion, $returnedClientScript->corePackages[$name]); + } + + public function providerScriptFiles() + { + return array( + array('/some/script.js', CClientScript::POS_HEAD, '/some/script.js'), + array('http://some/script.js', CClientScript::POS_BEGIN, 'http://some/script.js'), + array('/some/script.js', CClientScript::POS_END, '/some/script.js'), + ); + } + + /** + * @dataProvider providerScriptFiles + * + * @param string $url + * @param integer $position + * @param string $assertion + */ + public function testRegisterScriptFile($url, $position, $assertion) + { + $returnedClientScript = $this->_clientScript->registerScriptFile($url, $position); + $scriptFiles = $this->readAttribute($returnedClientScript, 'scriptFiles'); + $this->assertEquals($assertion, $scriptFiles[$position][$url]); + } + + public function providerScriptFilesWithHtmlOptions() + { + return array( + array( + '/some/script.js', + CClientScript::POS_HEAD, + array('defer'=>true), + array( + 'src'=>'/some/script.js', + 'defer'=>true + ) + ), + ); + } + + /** + * @dataProvider providerScriptFilesWithHtmlOptions + * + * @param string $url + * @param integer $position + * @param array $htmlOptions + * @param string $assertion + */ + public function testRegisterScriptFileWithHtmlOptions($url, $position, $htmlOptions, $assertion) + { + $returnedClientScript = $this->_clientScript->registerScriptFile($url, $position, $htmlOptions); + $scriptFiles = $this->readAttribute($returnedClientScript, 'scriptFiles'); + $this->assertEquals($assertion, $scriptFiles[$position][$url]); + } + + public function providerScripts() + { + return array( + array('jsId', "function() {alert('alert')}", CClientScript::POS_HEAD, "function() {alert('alert')}"), + array('jsId', "function() {alert('alert')}", CClientScript::POS_BEGIN, "function() {alert('alert')}"), + ); + } + + /** + * @dataProvider providerScripts + * + * @param string $id + * @param string $script + * @param integer $position + * @param string $assertion + */ + public function testRegisterScript($id, $script, $position, $assertion) { + $returnedClientScript = $this->_clientScript->registerScript($id, $script, $position); + $this->assertEquals($assertion, $returnedClientScript->scripts[$position][$id]); + } + + public function providerScriptsWithHtmlOptions() + { + return array( + array( + 'jsId', + "function() {alert('alert')}", + CClientScript::POS_HEAD, + array('defer'=>true), + array( + 'content'=>"function() {alert('alert')}", + 'defer'=>true, + ) + ), + ); + } + + /** + * @dataProvider providerScriptsWithHtmlOptions + * + * @param string $id + * @param string $script + * @param integer $position + * @param array $htmlOptions + * @param string $assertion + */ + public function testRegisterScriptWithHtmlOptions($id, $script, $position, $htmlOptions, $assertion) { + $returnedClientScript = $this->_clientScript->registerScript($id, $script, $position, $htmlOptions); + $this->assertEquals($assertion, $returnedClientScript->scripts[$position][$id]); + } + + public function providerRegisterCss() + { + return array( + array('myCssDiv', 'float:right;', '', array('myCssDiv'=>array('float:right;', ''))), + array('myCssDiv', 'float:right;', 'screen', array('myCssDiv'=>array('float:right;', 'screen'))) + ); + } + + /** + * @dataProvider providerRegisterCss + * + * @param string $id + * @param string $css + * @param string $media + * @param array $assertion + */ + public function testRegisterCss($id, $css, $media, $assertion) + { + $returnedClientScript = $this->_clientScript->registerCss($id, $css, $media); + $this->assertAttributeEquals($assertion, 'css', $returnedClientScript); + } + + public function providerRegisterMetaTag() + { + $data = array(); + + // Simple: + $metaTagData = array( + 'name'=>'testMetaTagName', + 'http-equiv'=>false, + 'content'=>'testMetaTagContent', + ); + $assertion = array( + $metaTagData + ); + $data[] = array($metaTagData['content'],$metaTagData['name'],$metaTagData['http-equiv'],array(),$assertion); + + // Http Equiv: + $metaTagData = array( + 'name'=>'testMetaTagHttpEquiv', + 'http-equiv'=>true, + 'content'=>'testMetaTagHttpEquivContent', + ); + $assertion = array( + $metaTagData + ); + $data[] = array($metaTagData['content'],$metaTagData['name'],$metaTagData['http-equiv'],array(),$assertion); + + return $data; + } + + /** + * @dataProvider providerRegisterMetaTag + * + * @param string $content + * @param string $name + * @param boolean $httpEquiv + * @param array $options + * @param array $assertion + */ + public function testRegisterMetaTag($content,$name,$httpEquiv,$options,$assertion) + { + $returnedClientScript = $this->_clientScript->registerMetaTag($content,$name,$httpEquiv,$options); + $this->assertAttributeEquals($assertion, 'metaTags', $returnedClientScript); + } + + /** + * @depends testRegisterMetaTag + */ + public function testRegisterDuplicatingMetaTag() { + $content='Test meta tag content'; + $name='test_meta_tag_name'; + $this->_clientScript->registerMetaTag($content,$name); + $this->_clientScript->registerMetaTag($content,$name); + + $metaTagData=array( + 'name'=>$name, + 'content'=>$content, + ); + $assertion=array( + $metaTagData, + $metaTagData + ); + $this->assertAttributeEquals($assertion, 'metaTags', $this->_clientScript); + } + + /* Test Script Renderers */ + + public function providerRenderScriptFiles() + { + return array( + array( + '/some/script.js', + CClientScript::POS_HEAD, + array(), + '' + ), + array( + '/some/script.js', + CClientScript::POS_BEGIN, + array(), + '' + ), + array( + '/some/script.js', + CClientScript::POS_END, + array(), + '' + ), + array( + '/options/script.js', + CClientScript::POS_HEAD, + array('defer'=>true), + '' + ), + array( + '/options/script.js', + CClientScript::POS_BEGIN, + array('defer'=>true), + '' + ), + array( + '/options/script.js', + CClientScript::POS_END, + array('defer'=>true), + '' + ), + ); + } + + /** + * @depends testRegisterScriptFile + * @depends testRegisterScriptFileWithHtmlOptions + * + * @dataProvider providerRenderScriptFiles + * + * @param string $url + * @param integer $position + * @param array $htmlOptions + * @param string $assertion + */ + public function testRenderScriptFiles($url, $position, $htmlOptions, $assertion) + { + $returnedClientScript = $this->_clientScript->registerScriptFile($url, $position, $htmlOptions); + $output = ''; + $returnedClientScript->render($output); + $this->assertContains($assertion, $output); + } + + public function providerRenderScripts() + { + return array( + array( + 'some_js_id', + "function() {alert('script')}", + CClientScript::POS_HEAD, + array(), + CHtml::script("function() {alert('script')}") + ), + array( + 'some_js_id', + "function() {alert('script')}", + CClientScript::POS_BEGIN, + array(), + CHtml::script("function() {alert('script')}") + ), + array( + 'some_js_id', + "function() {alert('script')}", + CClientScript::POS_END, + array(), + CHtml::script("function() {alert('script')}") + ), + array( + 'some_js_id', + "function() {alert('script')}", + CClientScript::POS_LOAD, + array(), + CHtml::script("function() {alert('script')}") + ), + array( + 'some_js_id', + "function() {alert('script')}", + CClientScript::POS_READY, + array(), + CHtml::script("function() {alert('script')}") + ), + // With HTML options + array( + 'option_js_id', + "function() {alert('script')}", + CClientScript::POS_HEAD, + array('defer'=>true), + CHtml::script("function() {alert('script')}",array('defer'=>true)) + ), + array( + 'option_js_id', + "function() {alert('script')}", + CClientScript::POS_BEGIN, + array('defer'=>true), + CHtml::script("function() {alert('script')}",array('defer'=>true)) + ), + array( + 'option_js_id', + "function() {alert('script')}", + CClientScript::POS_END, + array('defer'=>true), + CHtml::script("function() {alert('script')}",array('defer'=>true)) + ), + ); + } + + /** + * @depends testRegisterScript + * + * @dataProvider providerRenderScripts + * + * @param string $id + * @param string $script + * @param integer $position + * @param array $htmlOptions + * @param string $assertion + */ + public function testRenderScripts($id, $script, $position, $htmlOptions, $assertion) + { + $returnedClientScript = $this->_clientScript->registerScript($id, $script, $position, $htmlOptions); + $output = ''; + $returnedClientScript->render($output); + $this->assertContains($assertion, $output); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CControllerTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CControllerTest.php new file mode 100644 index 0000000..8715718 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CControllerTest.php @@ -0,0 +1,187 @@ +300, + ), + 'filter3 - internal', + ); + } + + public function actions() + { + return array( + 'external'=>'TestAction', + ); + } + + public function missingAction($actionName) + { + throw new CException('test missing'); + } + + public function filterFilter1($chain) + { + $chain->run(); + $this->internalFilter1++; + } + + public function filterFilter2($chain) + { + $this->internalFilter2++; + $chain->run(); + } + + public function filterFilter3($chain) + { + $this->internalFilter3++; + $chain->run(); + } + + public function actionInternal() + { + $this->internal++; + } + + public $a; + public $b; + public $c; + public $d; + + public function actionCreate($a,$b,$c=3,$d=4) + { + $this->a=$a; + $this->b=$b; + $this->c=$c; + $this->d=$d; + } +} + +class TestFilter extends CFilter +{ + public $expire=0; + public function filter($chain) + { + if($chain->controller->externalFilter<=1) + { + $chain->controller->externalFilter++; + $chain->run(); + } + } +} + +class TestAction extends CAction +{ + public function run() + { + $this->controller->external++; + } +} + +class CControllerTest extends CTestCase +{ + public function testDefaultProperties() + { + $app=new TestApplication; + $_SERVER['REQUEST_METHOD']='GET'; + $c=new CController('test/subtest'); + $this->assertEquals($c->id,'test/subtest'); + $this->assertEquals($c->filters(),array()); + $this->assertEquals($c->actions(),array()); + $this->assertNull($c->action); + $this->assertEquals($c->defaultAction,'index'); + $this->assertEquals($c->viewPath,$app->viewPath.DIRECTORY_SEPARATOR.'test/subtest'); + $this->setExpectedException('CHttpException'); + $c->missingAction('index'); + } + + public function testRunAction() + { + $app=new TestApplication; + $c=new TestController('test'); + $this->assertEquals($c->internal,0); + $this->assertEquals($c->external,0); + $this->assertEquals($c->internalFilter1,0); + $this->assertEquals($c->internalFilter2,0); + $this->assertEquals($c->internalFilter3,0); + $this->assertEquals($c->externalFilter,0); + + $c->run(''); + $this->assertEquals($c->internal,0); + $this->assertEquals($c->external,1); + $this->assertEquals($c->internalFilter1,1); + $this->assertEquals($c->internalFilter2,0); + $this->assertEquals($c->internalFilter3,1); + $this->assertEquals($c->externalFilter,1); + + $c->run('internal'); + $this->assertEquals($c->internal,1); + $this->assertEquals($c->external,1); + $this->assertEquals($c->internalFilter1,2); + $this->assertEquals($c->internalFilter2,1); + $this->assertEquals($c->internalFilter3,1); + $this->assertEquals($c->externalFilter,2); + + $c->run('external'); + $this->assertEquals($c->internal,1); + $this->assertEquals($c->external,1); + $this->assertEquals($c->internalFilter1,3); + $this->assertEquals($c->internalFilter2,1); + $this->assertEquals($c->internalFilter3,1); + $this->assertEquals($c->externalFilter,2); + + $this->setExpectedException('CException'); + $c->run('unknown'); + } + + public function testActionParams() + { + $app=new TestApplication; + $c=new TestController('test'); + + $_GET['a']=1; + $_GET['b']='2'; + $c->run('create'); + $this->assertTrue($c->a===1); + $this->assertTrue($c->b==='2'); + $this->assertTrue($c->c===3); + $this->assertTrue($c->d===4); + + $_GET['a']=11; + $_GET['b']='22'; + $_GET['d']='44'; + $c->run('create'); + $this->assertTrue($c->a===11); + $this->assertTrue($c->b==='22'); + $this->assertTrue($c->c===3); + $this->assertTrue($c->d==='44'); + } + + public function testActionParamsInvalid() + { + $app=new TestApplication; + $c=new TestController('test'); + $_GET=array('a'=>1); + $this->setExpectedException('CException'); + $c->run('create'); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CCookieCollectionTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CCookieCollectionTest.php new file mode 100644 index 0000000..466807f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CCookieCollectionTest.php @@ -0,0 +1,106 @@ +'testValue', + 'someEmptyCookie'=>'', + 'IntegerValue'=>1242, + 'cookieWithOptions'=>array( + 'value'=>'options', + 'httpOnly'=>true, + 'expire'=>12422, + ), + ); + protected $cookieBefore; + public function setUp() + { + $this->cookieBefore=$_COOKIE; + $_COOKIE['testGlobal']='value'; + $this->request=new TestHttpRequest; + $this->cookies=$this->request->cookies; + } + public function tearDown() + { + $_COOKIE=$this->cookieBefore; + } + /** + * @covers CCookieCollection::getCookies + * @covers CCookieCollection::__construct + */ + public function testConstructorCookieBuilding() + { + $this->assertTrue($this->cookies->contains('testGlobal')); + $this->assertTrue($this->cookies['testGlobal'] instanceof CHttpCookie); + $this->assertEquals($_COOKIE['testGlobal'], $this->cookies['testGlobal']->value); + } + /** + * @runInSeparateProcess + * @outputBuffering enabled + */ + public function testAdd() + { + $this->cookies['simple_name']=new CHttpCookie('simple_name', 'simple_value'); + $this->assertTrue($this->cookies['simple_name'] instanceof CHttpCookie); + $this->assertEquals('simple_value',$this->cookies['simple_name']->value); + // test if reference is not destroyed + $cookie=new CHttpCookie('referenceTest','someValue'); + $this->cookies[$cookie->name]=$cookie; + $this->assertTrue($this->cookies[$cookie->name] instanceof CHttpCookie); + $this->assertEquals('someValue',$this->cookies[$cookie->name]->value); + $cookie->value='SomeNewValue'; + $this->assertEquals($cookie->value,$this->cookies[$cookie->name]->value); + // test if cookies are added to internal array correctly + $this->assertTrue($this->cookies->contains('simple_name')); + $this->assertTrue($this->cookies->contains('referenceTest')); + $this->assertFalse($this->cookies->contains('someNonExistingCookie')); + } + /** + * @runInSeparateProcess + * @outputBuffering enabled + */ + public function testRemove() + { + // add some cookies to have something to base the tests (remove) + foreach($this->testCookies as $name=>$options) + { + if(is_array($options)) + { + $value=$options['value']; + unset($options['value']); + $cookie=new CHttpCookie($name,$value,$options); + } + else + $cookie=new CHttpCookie($name,$options); + $this->cookies[$cookie->name] = $cookie; + } + //check if cookies were added, else fail the test, since it makes no sence to do this, if there are no cookies + $this->assertTrue($this->cookies->contains('testCookieOne'),'A default cookie is missing! Check the testcase!'); + $this->assertTrue($this->cookies->contains('someEmptyCookie'),'A default cookie is missing! Check the testcase!'); + $this->assertTrue($this->cookies->contains('someEmptyCookie'),'A default cookie is missing! Check the testcase!'); + $this->assertTrue($this->cookies->contains('cookieWithOptions'),'A default cookie is missing! Check the testcase!'); + // Real tests below: + foreach($this->testCookies as $name=>$options) + { + if(is_array($options)) + { + $value=$options['value']; + unset($options['value']); + $this->assertTrue($this->cookies->remove($name,$options) instanceof CHttpCookie); + $this->assertFalse($this->cookies->contains($name),'Cookie(with options) has not been removed'); + } + else + { + $this->assertTrue($this->cookies->remove($name) instanceof CHttpCookie); + $this->assertFalse($this->cookies->contains($name)); + } + } + } + public function testGetRequest() + { + $this->assertTrue($this->cookies->getRequest() instanceof CHttpRequest); + $this->assertEquals($this->request,$this->cookies->getRequest(),'The collections does not contain the CHttpRequest instance it is stored in.'); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CDataProviderIteratorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CDataProviderIteratorTest.php new file mode 100644 index 0000000..938be21 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CDataProviderIteratorTest.php @@ -0,0 +1,70 @@ + + */ +class CDataProviderIteratorTest extends CTestCase +{ + public function pageSizes() + { + return array( + array(null), + array(1), + array(10), + array(110), + ); + } + + /** + * Tests the iterator + * + * @dataProvider pageSizes + */ + public function testIterator($pageSize) + { + $dataProvider = new CArrayDataProvider($this->generateData(100)); + $iterator = new CDataProviderIterator($dataProvider, $pageSize); + + $this->assertTrue($iterator->getDataProvider()===$dataProvider); + + $this->assertEquals(100, $iterator->getTotalItemCount()); + $this->assertEquals(100, count($iterator)); + + $n = 0; + foreach($iterator as $item) { + $this->assertEquals("Item ".$n,$item['name']); + $n++; + } + + $this->assertEquals(100, $n); + } + + /** + * @dataProvider pageSizes + */ + public function testInitWithDisabledPagination($pageSizes) + { + $dataProvider = new CArrayDataProvider($this->generateData(10), array( + 'pagination' => false, + )); + new CDataProviderIterator($dataProvider, $pageSizes); + } + + /** + * Generates some data to fill a dataProvider + * @param integer $totalItems the total number of items to generate + * @return array the data + */ + protected function generateData($totalItems) + { + $data = array(); + for($i = 0; $i < $totalItems; $i++) { + $data[] = array( + "id" => $i, + "name" => "Item ".$i, + ); + } + return $data; + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpCookieTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpCookieTest.php new file mode 100644 index 0000000..029b3ca --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpCookieTest.php @@ -0,0 +1,57 @@ +assertEquals('name',$cookie->name,'Constructor failure. Name should have been set there'); + $this->assertEquals('value',$cookie->value,'Constructor failure. Value should have been set there'); + $this->assertEquals('',$cookie->domain,'Default value for CHttpCookie::$domain has been touched'); + $this->assertEquals(0,$cookie->expire,'Default value for CHttpCookie::$expire has been touched'); + $this->assertEquals('/',$cookie->path,'Default value for CHttpCookie::$path has been touched'); + $this->assertFalse($cookie->secure,'Default value for CHttpCookie::$secure has been touched'); + $this->assertFalse($cookie->httpOnly,'Default value for CHttpCookie::$httpOnly has been touched'); + $options=array( + 'expire'=>123123, + 'httpOnly'=>true, + ); + // create cookie with options + $cookie2=new CHttpCookie('name2','value2',$options); + $this->assertEquals($options['expire'],$cookie2->expire,'Configure inside the Constructor has been failed'); + $this->assertEquals($options['httpOnly'],$cookie2->httpOnly,'Configure inside the Constructor has been failed'); + //configure afterwards + $cookie->configure($options); + $this->assertEquals($options['expire'],$cookie->expire); + $this->assertEquals($options['httpOnly'],$cookie->httpOnly); + // Set name and value via configure (should have no effect) + $name=$cookie->name; + $cookie->configure(array('name'=>'someNewName')); + $this->assertEquals($name,$cookie->name); + $value=$cookie->value; + $cookie->configure(array('value'=>'someNewValue')); + $this->assertEquals($value,$cookie->value); + //new configure should not override already set configuration + $this->assertEquals($options['httpOnly'],$cookie->httpOnly); + } + /** + * @covers CHttpCookie::__toString + */ + public function test__ToString() + { + $cookie=new CHttpCookie('name','someValue'); + // Note on http://www.php.net/manual/en/language.oop5.magic.php#object.tostring + ob_start(); + echo $cookie; + $this->assertEquals(ob_get_clean(),$cookie->value); + if(version_compare(PHP_VERSION,'5.2','>=')) + { + $this->assertEquals($cookie->value,(string)$cookie); + } + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpRequestTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpRequestTest.php new file mode 100644 index 0000000..c2c3d82 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpRequestTest.php @@ -0,0 +1,273 @@ +assertEquals($result,CHttpRequest::parseAcceptHeader($header),$errorString); + } + + /** + * @covers CHttpRequest::compareAcceptTypes + * @dataProvider acceptContentTypeArrayMapDataProvider + */ + public function testCompareAcceptTypes($a,$b,$result,$errorString='Compare of content type array maps did not give expected preference') + { + $this->assertEquals($result,CHttpRequest::compareAcceptTypes($a,$b),$errorString); + // make sure that inverse comparison holds + $this->assertEquals($result*-1,CHttpRequest::compareAcceptTypes($b,$a),'(Inverse) '.$errorString); + } + + public function acceptHeaderDataProvider() + { + return array( + // null header + array( + null, + array(), + 'Parsing null Accept header did not return empty array', + ), + // empty header + array( + '', + array(), + 'Parsing empty Accept header did not return empty array', + ), + // nonsense header, containing no valid accept types (but containing the characters that the header is split on) + array( + 'gsf,\'yas\'erys"rt;,";s,y s;,', + array(), + 'Parsing completely invalid Accept header did not return empty array', + ), + // valid header containing only content types + array( + 'application/xhtml+xml,text/html,*/json,image/png', + array( + array( + 'type'=>'application', + 'subType'=>'xhtml', + 'baseType'=>'xml', + 'params'=>array( + 'q'=>1, + ), + ), + array( + 'type'=>'text', + 'subType'=>'html', + 'baseType'=>null, + 'params'=>array( + 'q'=>1, + ), + ), + array( + 'type'=>'*', + 'subType'=>'json', + 'baseType'=>null, + 'params'=>array( + 'q'=>1, + ), + ), + array( + 'type'=>'image', + 'subType'=>'png', + 'baseType'=>null, + 'params'=>array( + 'q'=>1, + ), + ), + ), + 'Parsing valid Accept header containing only content types did not return correct result', + ), + // valid header containing all details + array( + 'application/xhtml+xml;q=0.9,text/html,*/json;q=4;level=three,image/png;a=1;b=2;c=3', + array( + array( + 'type'=>'application', + 'subType'=>'xhtml', + 'baseType'=>'xml', + 'params'=>array( + 'q'=>0.9, + ), + ), + array( + 'type'=>'text', + 'subType'=>'html', + 'baseType'=>null, + 'params'=>array( + 'q'=>1, + ), + ), + array( + 'type'=>'*', + 'subType'=>'json', + 'baseType'=>null, + 'params'=>array( + 'q'=>1, + 'level'=>'three', + ), + ), + array( + 'type'=>'image', + 'subType'=>'png', + 'baseType'=>null, + 'params'=>array( + 'q'=>1, + 'a'=>1, + 'b'=>2, + 'c'=>3, + ), + ), + ), + 'Parsing valid Accept header containing all details did not return correct result', + ), + // partially valid header containing all details (no , after */json) + array( + 'application/xhtml+xml;q=0.9,text/html,*/json;q=4;level=three image/png;a=1;b=2;c=3', + array( + array( + 'type'=>'application', + 'subType'=>'xhtml', + 'baseType'=>'xml', + 'params'=>array( + 'q'=>0.9, + ), + ), + array( + 'type'=>'text', + 'subType'=>'html', + 'baseType'=>null, + 'params'=>array( + 'q'=>1, + ), + ), + array( + 'type'=>'*', + 'subType'=>'json', + 'baseType'=>null, + 'params'=>array( + 'q'=>1, + 'level'=>'three', + ), + ), + ), + 'Parsing partially valid Accept header containing all details did not return correct result', + ), + ); + } + + public function acceptContentTypeArrayMapDataProvider() + { + return array( + array( + array( + 'type'=>'application', + 'subType'=>'xhtml', + 'baseType'=>'xml', + 'params'=>array( + 'q'=>0.99, + ), + ), + array( + 'type'=>'text', + 'subType'=>'html', + 'baseType'=>null, + 'params'=>array( + 'q'=>(double)1, + ), + ), + 1, + 'Comparing different q did not assign correct preference', + ), + array( + array( + 'type'=>'application', + 'subType'=>'xhtml', + 'baseType'=>'xml', + 'params'=>array( + 'q'=>0.5, + ), + ), + array( + 'type'=>'*', + 'subType'=>'html', + 'baseType'=>null, + 'params'=>array( + 'q'=>0.5, + ), + ), + -1, + 'Comparing type wildcard with specific type did not assign correct preference', + ), + array( + array( + 'type'=>'application', + 'subType'=>'*', + 'baseType'=>'xml', + 'params'=>array( + 'q'=>0.5, + ), + ), + array( + 'type'=>'text', + 'subType'=>'html', + 'baseType'=>null, + 'params'=>array( + 'q'=>0.5, + ), + ), + 1, + 'Comparing subType wildcard with specific subType did not assign correct preference', + ), + array( + array( + 'type'=>'*', + 'subType'=>'xhtml', + 'baseType'=>'xml', + 'params'=>array( + 'q'=>0.9, + 'foo'=>'bar2', + ), + ), + array( + 'type'=>'*', + 'subType'=>'html', + 'baseType'=>null, + 'params'=>array( + 'q'=>0.9, + 'foo'=>'bar', + 'test'=>'drive', + ), + ), + 1, + 'Comparing different number of params did not assign correct preference', + ), + array( + array( + 'type'=>'*', + 'subType'=>'xhtml', + 'baseType'=>'xml', + 'params'=>array( + 'q'=>0.9, + 'foo'=>'bar', + ), + ), + array( + 'type'=>'*', + 'subType'=>'html', + 'baseType'=>null, + 'params'=>array( + 'q'=>0.9, + 'foo'=>'bar', + ), + ), + 0, + 'Comparing equal type, subType, q and number of params did not return equality', + ), + ); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpSessionTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpSessionTest.php new file mode 100644 index 0000000..18c7664 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CHttpSessionTest.php @@ -0,0 +1,36 @@ +session->gCProbability = $gcProb; + $value = Yii::app()->session->gCProbability; + $this->assertInternalType('float', $value); + $this->assertLessThanOrEqual(1, $value); + $this->assertGreaterThanOrEqual(0, $value); + $this->assertLessThanOrEqual(1 / 21474836.47, abs($gcProb - $value)); + } + + /** + * @covers CHttpSession::getGCProbability + * @covers CHttpSession::setGCProbability + */ + public function testSetGet() { + Yii::app()->setComponents(array('session' => array( + 'class' => 'CHttpSession', + 'cookieMode' => 'none', + 'savePath' => sys_get_temp_dir(), + 'sessionName' => 'CHttpSessionTest', + 'timeout' => 5, + ))); + /** @var $sm CHttpSession */ + + $this->checkProb(1); + $this->checkProb(0); + $gcProb = 1.0; + while ($gcProb > 1 / 2147483647) { + $this->checkProb($gcProb); + $gcProb = $gcProb / 9; + } + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSortTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSortTest.php new file mode 100644 index 0000000..269d7e1 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSortTest.php @@ -0,0 +1,84 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->db=new CDbConnection('sqlite::memory:'); + $this->db->active=true; + $this->db->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/CSortTest.sql')); + CActiveRecord::$db=$this->db; + } + + public function tearDown(){ + $this->db->active=false; + } + + /** + * Tests for acceptance of fields with dots in + * CSort::attributes. + * + * @return void + */ + function testGetDirectionsWithDots(){ + $_GET['sort'] = 'comments.id'; + + $criteria = new CDbCriteria(); + $criteria->with = 'comments'; + + $sort = new CSort('TestPost'); + $sort->attributes = array( + 'id', + 'comments.id' => array( + 'asc'=>'comments.id', + 'desc'=>'comments.id desc', + ), + ); + $sort->applyOrder($criteria); + $directions = $sort->getDirections(); + + $this->assertTrue(isset($directions['comments.id'])); + } +} + + +class TestPost extends CActiveRecord { + public static function model($className=__CLASS__) { + return parent::model($className); + } + + public function tableName() { + return 'post'; + } + + public function relations() { + return array( + 'comments'=>array(self::HAS_MANY, 'TestComment', 'post_id'), + ); + } +} + +class TestComment extends CActiveRecord { + public static function model($className=__CLASS__) { + return parent::model($className); + } + + public function tableName() { + return 'comment'; + } + + public function relations() { + return array( + 'post'=>array(self::BELONGS_TO, 'TestPost', 'post_id'), + ); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSortTest.sql b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSortTest.sql new file mode 100644 index 0000000..90b8654 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSortTest.sql @@ -0,0 +1,12 @@ +CREATE TABLE comment ( + id INTEGER PRIMARY KEY, + post_id INTEGER, + text text, + created_at INTEGER +); + +CREATE TABLE post ( + id INTEGER PRIMARY KEY, + created_at INTEGER, + title VARCHAR(255) +); \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSqlDataProviderTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSqlDataProviderTest.php new file mode 100644 index 0000000..c5767c0 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CSqlDataProviderTest.php @@ -0,0 +1,39 @@ +markTestSkipped('PDO and SQLite extensions are required.'); + + $this->db=new CDbConnection('sqlite::memory:'); + $this->db->active=true; + $this->db->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/../db/data/sqlite.sql')); + CActiveRecord::$db=$this->db; + } + + public function tearDown() + { + $this->db->active=false; + } + + /** + * https://github.com/yiisoft/yii/issues/2449 + */ + public function testFetchKeysWithDbCommandSpecifiedAndPdoFetchObjEnabled() + { + $command1=$this->db->createCommand()->select('*')->from('posts')->setFetchMode(PDO::FETCH_ASSOC); + $dataProvider1=new CSqlDataProvider($command1); + $this->assertSame(array('1','2','3','4','5'),$dataProvider1->keys); + + $command2=$this->db->createCommand()->select('*')->from('posts')->setFetchMode(PDO::FETCH_OBJ); + $dataProvider2=new CSqlDataProvider($command2); + $this->assertSame(array('1','2','3','4','5'),$dataProvider2->keys); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUploadedFileTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUploadedFileTest.php new file mode 100644 index 0000000..b42761c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUploadedFileTest.php @@ -0,0 +1,127 @@ +'test_file.dat', + 'type'=>'somemime/type', + 'tmp_name'=>'/tmp/test_file', + 'error'=>UPLOAD_ERR_OK, + 'size'=>100, + ); + $uploadedFile=CUploadedFile::getInstanceByName($inputName); + $this->assertTrue(is_object($uploadedFile),'Unable to get uploaded file by name!'); + $this->assertEquals($_FILES[$inputName]['name'],$uploadedFile->getName(),'Wrong name!'); + $this->assertEquals($_FILES[$inputName]['type'],$uploadedFile->getType(),'Wrong type!'); + $this->assertEquals($_FILES[$inputName]['tmp_name'],$uploadedFile->getTempName(),'Wrong temp name!'); + $this->assertEquals($_FILES[$inputName]['error'],$uploadedFile->getError(),'Wrong error!'); + $this->assertEquals($_FILES[$inputName]['size'],$uploadedFile->getSize(),'Wrong size!'); + } + + public function testGetInstancesByName() + { + $inputName='test_name'; + $inputCount=3; + $_FILES[$inputName]=array( + 'name'=>array(), + 'type'=>array(), + 'tmp_name'=>array(), + 'error'=>array(), + 'size'=>array(), + ); + for($i=0;$i<$inputCount;$i++) + { + $_FILES[$inputName]['name'][$i]='test_file_'.$i.'.dat'; + $_FILES[$inputName]['type'][$i]='mime/type'.$i; + $_FILES[$inputName]['tmp_name'][$i]='/tmp/file'.$i; + $_FILES[$inputName]['error'][$i]=UPLOAD_ERR_OK; + $_FILES[$inputName]['size'][$i]=500+$i*10; + } + + $uploadedFiles=CUploadedFile::getInstancesByName($inputName); + $this->assertFalse(empty($uploadedFiles),'Unable to get instances by name!'); + for($i=0;$i<$inputCount;$i++) + { + $this->assertEquals($_FILES[$inputName]['name'][$i],$uploadedFiles[$i]->getName(),'Wrong name!'); + $this->assertEquals($_FILES[$inputName]['type'][$i],$uploadedFiles[$i]->getType(),'Wrong type!'); + $this->assertEquals($_FILES[$inputName]['tmp_name'][$i],$uploadedFiles[$i]->getTempName(),'Wrong temp name!'); + $this->assertEquals($_FILES[$inputName]['error'][$i],$uploadedFiles[$i]->getError(),'Wrong error!'); + $this->assertEquals($_FILES[$inputName]['size'][$i],$uploadedFiles[$i]->getSize(),'Wrong size!'); + } + } + + public function testGetInstanceByNestedName() + { + $baseInputName='SomeModel'; + $subInputName='test_name'; + $_FILES[$baseInputName]=array( + 'name'=>array( + $subInputName=>'test_file.dat' + ), + 'type'=>array( + $subInputName=>'somemime/type' + ), + 'tmp_name'=>array( + $subInputName=>'/tmp/test_file' + ), + 'error'=>array( + $subInputName=>UPLOAD_ERR_OK + ), + 'size'=>array( + $subInputName=>100 + ), + ); + $uploadedFile=CUploadedFile::getInstanceByName("{$baseInputName}[{$subInputName}]"); + $this->assertTrue(is_object($uploadedFile),'Unable to get uploaded file by nested name!'); + $this->assertEquals($_FILES[$baseInputName]['name'][$subInputName],$uploadedFile->getName(),'Wrong name!'); + $this->assertEquals($_FILES[$baseInputName]['type'][$subInputName],$uploadedFile->getType(),'Wrong type!'); + $this->assertEquals($_FILES[$baseInputName]['tmp_name'][$subInputName],$uploadedFile->getTempName(),'Wrong temp name!'); + $this->assertEquals($_FILES[$baseInputName]['error'][$subInputName],$uploadedFile->getError(),'Wrong error!'); + $this->assertEquals($_FILES[$baseInputName]['size'][$subInputName],$uploadedFile->getSize(),'Wrong size!'); + } + + /** + * @depends testGetInstancesByName + * + * @see https://github.com/yiisoft/yii/issues/159 + */ + public function testGetInstancesByNamePartOfOtherName() + { + $baseInputName='base_name'; + $tailedInputName=$baseInputName.'_tail'; + + $_FILES[$baseInputName]=array( + 'name'=>$baseInputName.'.dat', + 'type'=>'somemime/'.$baseInputName, + 'tmp_name'=>'/tmp/'.$baseInputName, + 'error'=>UPLOAD_ERR_OK, + 'size'=>100, + ); + $_FILES[$tailedInputName]=array( + 'name'=>$tailedInputName.'.dat', + 'type'=>'somemime/'.$tailedInputName, + 'tmp_name'=>'/tmp/'.$tailedInputName, + 'error'=>UPLOAD_ERR_OK, + 'size'=>100, + ); + + $uploadedFiles=CUploadedFile::getInstancesByName($baseInputName); + foreach($uploadedFiles as $uploadedFile) + $this->assertEquals($_FILES[$baseInputName]['name'],$uploadedFile->getName(),'Wrong file fetched!'); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUrlManagerTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUrlManagerTest.php new file mode 100644 index 0000000..868a2b2 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUrlManagerTest.php @@ -0,0 +1,553 @@ +'=>'article/read', + 'article///*'=>'article/read', + 'a/<_a>/*'=>'article', + 'register/*'=>'user', + 'home/*'=>'', + 'ad/*'=>'admin/index/list', + '<c:(post|comment)>/<id:\d+>/<a:(create|update|delete)>'=>'<c>/<a>', + '<c:(post|comment)>/<id:\d+>'=>'<c>/view', + '<c:(post|comment)>s/*'=>'<c>/list', + 'http://<user:\w+>.example.com/<lang:\w+>/profile'=>'user/profile', + 'currency/<c:\p{Sc}>'=>'currency/info', + ); + $entries=array( + array( + 'pathInfo'=>'article/123', + 'route'=>'article/read', + 'params'=>array('id'=>'123'), + ), + array( + 'pathInfo'=>'article/123/name/value', + 'route'=>'article/123/name/value', + 'params'=>array(), + ), + array( + 'pathInfo'=>'article/2000/title goes here', + 'route'=>'article/read', + 'params'=>array('year'=>'2000','title'=>'title goes here'), + ), + array( + 'pathInfo'=>'article/2000/title goes here/name/value', + 'route'=>'article/read', + 'params'=>array('year'=>'2000','title'=>'title goes here','name'=>'value'), + ), + array( + 'pathInfo'=>'register/username/admin', + 'route'=>'user', + 'params'=>array('username'=>'admin'), + ), + array( + 'pathInfo'=>'home/name/value/name1/value1', + 'route'=>'', + 'params'=>array('name'=>'value','name1'=>'value1'), + ), + array( + 'pathInfo'=>'home2/name/value/name1/value1', + 'route'=>'home2/name/value/name1/value1', + 'params'=>array(), + ), + array( + 'pathInfo'=>'post', + 'route'=>'post', + 'params'=>array(), + ), + array( + 'pathInfo'=>'post/read', + 'route'=>'post/read', + 'params'=>array(), + ), + array( + 'pathInfo'=>'post/read/id/100', + 'route'=>'post/read/id/100', + 'params'=>array(), + ), + array( + 'pathInfo'=>'', + 'route'=>'', + 'params'=>array(), + ), + array( + 'pathInfo'=>'ad/name/value', + 'route'=>'admin/index/list', + 'params'=>array('name'=>'value'), + ), + array( + 'pathInfo'=>'admin/name/value', + 'route'=>'admin/name/value', + 'params'=>array(), + ), + array( + 'pathInfo'=>'posts', + 'route'=>'post/list', + 'params'=>array(), + ), + array( + 'pathInfo'=>'posts/page/3', + 'route'=>'post/list', + 'params'=>array('page'=>3), + ), + array( + 'pathInfo'=>'post/3', + 'route'=>'post/view', + 'params'=>array('id'=>3), + ), + array( + 'pathInfo'=>'post/3/delete', + 'route'=>'post/delete', + 'params'=>array('id'=>3), + ), + array( + 'pathInfo'=>'post/3/delete/a', + 'route'=>'post/3/delete/a', + 'params'=>array(), + ), + array( + 'pathInfo'=>'en/profile', + 'route'=>'user/profile', + 'params'=>array('user'=>'admin','lang'=>'en'), + ), + array( + 'pathInfo'=>'currency/$', + 'route'=>'currency/info', + 'params'=>array('c'=>'$'), + ), + ); + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'request'=>array( + 'class'=>'TestHttpRequest', + 'scriptUrl'=>'/app/index.php', + ), + ), + ); + $app=new TestApplication($config); + $app->controllerPath=dirname(__FILE__).DIRECTORY_SEPARATOR.'controllers'; + $request=$app->request; + $_SERVER['HTTP_HOST']='admin.example.com'; + $um=new CUrlManager; + $um->urlSuffix='.html'; + $um->urlFormat='path'; + $um->rules=$rules; + $um->init($app); + foreach($entries as $entry) + { + $request->pathInfo=$entry['pathInfo']; + $_GET=array(); + $route=$um->parseUrl($request); + $this->assertEquals($entry['route'],$route); + $this->assertEquals($entry['params'],$_GET); + // test the .html version + $request->pathInfo=$entry['pathInfo'].'.html'; + $_GET=array(); + $route=$um->parseUrl($request); + $this->assertEquals($entry['route'],$route); + $this->assertEquals($entry['params'],$_GET); + } + } + + public function testcreateUrlWithPathFormat() + { + $rules=array( + 'article/<id:\d+>'=>'article/read', + 'article/<year:\d{4}>/<title>/*'=>'article/read', + 'a/<_a>/*'=>'article', + 'register/*'=>'user', + 'home/*'=>'', + '<c:(post|comment)>/<id:\d+>/<a:(create|update|delete)>'=>'<c>/<a>', + '<c:(post|comment)>/<id:\d+>'=>'<c>/view', + '<c:(post|comment)>s/*'=>'<c>/list', + 'http://<user:\w+>.example.com/<lang:\w+>/profile'=>'user/profile', + 'currency/<c:\p{Sc}>'=>'currency/info', + ); + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'request'=>array( + 'class'=>'TestHttpRequest', + ), + ), + ); + $_SERVER['HTTP_HOST']='user.example.com'; + $app=new TestApplication($config); + $entries=array( + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'/apps/index.php/post/123?name1=value1', + 'url2'=>'/apps/post/123?name1=value1', + 'url3'=>'/apps/post/123.html?name1=value1', + 'route'=>'post/view', + 'params'=>array( + 'id'=>'123', + 'name1'=>'value1', + ), + ), + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'/apps/index.php/post/123/update?name1=value1', + 'url2'=>'/apps/post/123/update?name1=value1', + 'url3'=>'/apps/post/123/update.html?name1=value1', + 'route'=>'post/update', + 'params'=>array( + 'id'=>'123', + 'name1'=>'value1', + ), + ), + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'/apps/index.php/posts/page/123', + 'url2'=>'/apps/posts/page/123', + 'url3'=>'/apps/posts/page/123.html', + 'route'=>'post/list', + 'params'=>array( + 'page'=>'123', + ), + ), + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'/apps/index.php/article/123?name1=value1', + 'url2'=>'/apps/article/123?name1=value1', + 'url3'=>'/apps/article/123.html?name1=value1', + 'route'=>'article/read', + 'params'=>array( + 'id'=>'123', + 'name1'=>'value1', + ), + ), + array( + 'scriptUrl'=>'/index.php', + 'url'=>'/index.php/article/123?name1=value1', + 'url2'=>'/article/123?name1=value1', + 'url3'=>'/article/123.html?name1=value1', + 'route'=>'article/read', + 'params'=>array( + 'id'=>'123', + 'name1'=>'value1', + ), + ), + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'/apps/index.php/article/2000/the_title/name1/value1', + 'url2'=>'/apps/article/2000/the_title/name1/value1', + 'url3'=>'/apps/article/2000/the_title/name1/value1.html', + 'route'=>'article/read', + 'params'=>array( + 'year'=>'2000', + 'title'=>'the_title', + 'name1'=>'value1', + ), + ), + array( + 'scriptUrl'=>'/index.php', + 'url'=>'/index.php/article/2000/the_title/name1/value1', + 'url2'=>'/article/2000/the_title/name1/value1', + 'url3'=>'/article/2000/the_title/name1/value1.html', + 'route'=>'article/read', + 'params'=>array( + 'year'=>'2000', + 'title'=>'the_title', + 'name1'=>'value1', + ), + ), + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'/apps/index.php/post/edit/id/123/name1/value1', + 'url2'=>'/apps/post/edit/id/123/name1/value1', + 'url3'=>'/apps/post/edit/id/123/name1/value1.html', + 'route'=>'post/edit', + 'params'=>array( + 'id'=>'123', + 'name1'=>'value1', + ), + ), + array( + 'scriptUrl'=>'/index.php', + 'url'=>'http://admin.example.com/en/profile', + 'url2'=>'http://admin.example.com/en/profile', + 'url3'=>'http://admin.example.com/en/profile.html', + 'route'=>'user/profile', + 'params'=>array( + 'user'=>'admin', + 'lang'=>'en', + ), + ), + array( + 'scriptUrl'=>'/index.php', + 'url'=>'/en/profile', + 'url2'=>'/en/profile', + 'url3'=>'/en/profile.html', + 'route'=>'user/profile', + 'params'=>array( + 'user'=>'user', + 'lang'=>'en', + ), + ), + array( + 'scriptUrl'=>'/index.php', + 'url'=>'/index.php/currency/%EF%BC%84', + 'url2'=>'/currency/%EF%BC%84', + 'url3'=>'/currency/%EF%BC%84.html', + 'route'=>'currency/info', + 'params'=>array( + 'c'=>'$', + ), + ), + ); + foreach($entries as $entry) + { + $app->request->baseUrl=null; // reset so that it can be determined based on scriptUrl + $app->request->scriptUrl=$entry['scriptUrl']; + for($matchValue=0;$matchValue<2;$matchValue++) + { + $um=new CUrlManager; + $um->urlFormat='path'; + $um->rules=$rules; + $um->matchValue=$matchValue!=0; + $um->init($app); + $url=$um->createUrl($entry['route'],$entry['params']); + $this->assertEquals($entry['url'],$url,'matchValue='.($um->matchValue ? 'true' : 'false')); + + $um=new CUrlManager; + $um->urlFormat='path'; + $um->rules=$rules; + $um->matchValue=$matchValue!=0; + $um->init($app); + $um->showScriptName=false; + $url=$um->createUrl($entry['route'],$entry['params']); + $this->assertEquals($entry['url2'],$url,'matchValue='.($um->matchValue ? 'true' : 'false')); + + $um->urlSuffix='.html'; + $url=$um->createUrl($entry['route'],$entry['params']); + $this->assertEquals($entry['url3'],$url,'matchValue='.($um->matchValue ? 'true' : 'false')); + } + } + } + + public function testParseUrlWithGetFormat() + { + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'request'=>array( + 'class'=>'TestHttpRequest', + 'scriptUrl'=>'/app/index.php', + ), + ), + ); + $entries=array( + array( + 'route'=>'article/read', + 'name'=>'value', + ), + ); + $app=new TestApplication($config); + $request=$app->request; + $um=new CUrlManager; + $um->urlFormat='get'; + $um->routeVar='route'; + $um->init($app); + foreach($entries as $entry) + { + $_GET=$entry; + $route=$um->parseUrl($request); + $this->assertEquals($entry['route'],$route); + $this->assertEquals($_GET,$entry); + } + } + + public function testCreateUrlWithGetFormat() + { + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'request'=>array( + 'class'=>'TestHttpRequest', + ), + ), + ); + $app=new TestApplication($config); + $entries=array( + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'/apps/index.php?route=article/read&name=value&name1=value1', + 'url2'=>'/apps/?route=article/read&name=value&name1=value1', + 'route'=>'article/read', + 'params'=>array( + 'name'=>'value', + 'name1'=>'value1', + ), + ), + array( + 'scriptUrl'=>'/index.php', + 'url'=>'/index.php?route=article/read&name=value&name1=value1', + 'url2'=>'/?route=article/read&name=value&name1=value1', + 'route'=>'article/read', + 'params'=>array( + 'name'=>'value', + 'name1'=>'value1', + ), + ), + ); + foreach($entries as $entry) + { + $app->request->baseUrl=null; + $app->request->scriptUrl=$entry['scriptUrl']; + $um=new CUrlManager; + $um->urlFormat='get'; + $um->routeVar='route'; + $um->init($app); + $url=$um->createUrl($entry['route'],$entry['params'],'&'); + $this->assertEquals($url,$entry['url']); + + $um=new CUrlManager; + $um->urlFormat='get'; + $um->routeVar='route'; + $um->showScriptName=false; + $um->init($app); + $url=$um->createUrl($entry['route'],$entry['params'],'&'); + $this->assertEquals($url,$entry['url2']); + } + } + + public function testDefaultParams() + { + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'request'=>array( + 'class'=>'TestHttpRequest', + ), + ), + ); + $app=new TestApplication($config); + + $app->request->baseUrl=null; // reset so that it can be determined based on scriptUrl + $app->request->scriptUrl='/apps/index.php'; + $um=new CUrlManager; + $um->urlFormat='path'; + $um->rules=array( + ''=>array('site/page', 'defaultParams'=>array('view'=>'about')), + 'posts'=>array('post/index', 'defaultParams'=>array('page'=>1)), + '<slug:[0-9a-z-]+>' => array('news/list', 'defaultParams' => array('page' => 1)), + ); + $um->init($app); + + $url=$um->createUrl('site/page',array('view'=>'about')); + $this->assertEquals('/apps/index.php/',$url); + $app->request->pathInfo=''; + $_GET=array(); + $route=$um->parseUrl($app->request); + $this->assertEquals('site/page',$route); + $this->assertEquals(array('view'=>'about'),$_GET); + + $url=$um->createUrl('post/index',array('page'=>1)); + $this->assertEquals('/apps/index.php/posts',$url); + $app->request->pathInfo='posts'; + $_GET=array(); + $route=$um->parseUrl($app->request); + $this->assertEquals('post/index',$route); + $this->assertEquals(array('page'=>'1'),$_GET); + + $url=$um->createUrl('news/list', array('slug' => 'example', 'page' => 1)); + $this->assertEquals('/apps/index.php/example',$url); + $app->request->pathInfo='example'; + $_GET=array(); + $route=$um->parseUrl($app->request); + $this->assertEquals('news/list',$route); + $this->assertEquals(array('slug'=>'example', 'page'=>'1'),$_GET); + } + + public function testVerb() + { + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'request'=>array( + 'class'=>'TestHttpRequest', + ), + ), + ); + $rules=array( + 'article/<id:\d+>'=>array('article/read', 'verb'=>'GET'), + 'article/update/<id:\d+>'=>array('article/update', 'verb'=>'POST'), + 'article/update/*'=>'article/admin', + ); + + $entries=array( + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'article/123', + 'verb'=>'GET', + 'route'=>'article/read', + ), + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'article/update/123', + 'verb'=>'POST', + 'route'=>'article/update', + ), + array( + 'scriptUrl'=>'/apps/index.php', + 'url'=>'article/update/123', + 'verb'=>'GET', + 'route'=>'article/admin', + ), + ); + + foreach($entries as $entry) + { + $_SERVER['REQUEST_METHOD']=$entry['verb']; + $app=new TestApplication($config); + $app->request->baseUrl=null; // reset so that it can be determined based on scriptUrl + $app->request->scriptUrl=$entry['scriptUrl']; + $app->request->pathInfo=$entry['url']; + $um=new CUrlManager; + $um->urlFormat='path'; + $um->rules=$rules; + $um->init($app); + $route=$um->parseUrl($app->request); + $this->assertEquals($entry['route'],$route); + } + } + + public function testParsingOnly() + { + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'request'=>array( + 'class'=>'TestHttpRequest', + ), + ), + ); + $rules=array( + '(articles|article)/<id:\d+>'=>array('article/read', 'parsingOnly'=>true), + 'article/<id:\d+>'=>array('article/read', 'verb'=>'GET'), + ); + + $_SERVER['REQUEST_METHOD']='GET'; + $app=new TestApplication($config); + $app->request->baseUrl=null; // reset so that it can be determined based on scriptUrl + $app->request->scriptUrl='/apps/index.php'; + $app->request->pathInfo='articles/123'; + $um=new CUrlManager; + $um->urlFormat='path'; + $um->rules=$rules; + $um->init($app); + + $route=$um->parseUrl($app->request); + $this->assertEquals('article/read',$route); + + $url=$um->createUrl('article/read', array('id'=>345)); + $this->assertEquals('/apps/index.php/article/345',$url); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUrlRuleTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUrlRuleTest.php new file mode 100644 index 0000000..26a3b3d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/CUrlRuleTest.php @@ -0,0 +1,80 @@ +<?php + +Yii::import('system.web.CUrlManager'); + +class CUrlRuleTest extends CTestCase +{ + private $app; + + public function setUp() + { + $config=array( + 'basePath'=>dirname(__FILE__), + 'components'=>array( + 'request'=>array( + 'class'=>'TestHttpRequest', + ), + ), + ); + $_SERVER['HTTP_HOST']='user.example.com'; + $this->app=new TestApplication($config); + } + + public function testParseUrlMatchValue() + { + $rules=array( + array( + 'route'=>'article/read', + 'pattern'=>'article/<id:\d+>', + 'scriptUrl'=>'/apps/index.php', + 'entries'=>array( + array( + 'route'=>'article/read', + 'params'=>array( + 'id'=>'123', + 'name1'=>'value1', + ), + 'url'=>'article/123?name1=value1', + ), + array( + 'route'=>'article/read', + 'params'=>array( + 'id'=>'abc', + 'name1'=>'value1', + ), + 'url'=>false, + ), + array( + 'route'=>'article/read', + 'params'=>array( + 'id'=>"123\n", + 'name1'=>'value1', + ), + 'url'=>false, + ), + array( + 'route'=>'article/read', + 'params'=>array( + 'id'=>'0x1', + 'name1'=>'value1', + ), + 'url'=>false, + ), + ), + ), + ); + $um=new CUrlManager; + foreach($rules as $rule) + { + $this->app->request->baseUrl=null; // reset so that it can be determined based on scriptUrl + $this->app->request->scriptUrl=$rule['scriptUrl']; + $ur=new CUrlRule($rule['route'],$rule['pattern']); + $ur->matchValue=true; + foreach($rule['entries'] as $entry) + { + $url=$ur->createUrl($um,$entry['route'],$entry['params'],'&'); + $this->assertEquals($entry['url'],$url); + } + } + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/AuthManagerTestBase.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/AuthManagerTestBase.php new file mode 100644 index 0000000..43a993d --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/AuthManagerTestBase.php @@ -0,0 +1,243 @@ +<?php + +abstract class AuthManagerTestBase extends CTestCase +{ + protected $auth; + + public function testcreateAuthItem() + { + $type=CAuthItem::TYPE_TASK; + $name='editUser'; + $description='edit a user'; + $bizRule='checkUserIdentity()'; + $data=array(1,2,3); + $item=$this->auth->createAuthItem($name,$type,$description,$bizRule,$data); + $this->assertTrue($item instanceof CAuthItem); + $this->assertEquals($item->type,$type); + $this->assertEquals($item->name,$name); + $this->assertEquals($item->description,$description); + $this->assertEquals($item->bizRule,$bizRule); + $this->assertEquals($item->data,$data); + + // test shortcut + $name2='createUser'; + $item2=$this->auth->createRole($name2,$description,$bizRule,$data); + $this->assertEquals($item2->type,CAuthItem::TYPE_ROLE); + + // test adding an item with the same name + $this->setExpectedException('CException'); + $this->auth->createAuthItem($name,$type,$description,$bizRule,$data); + } + + public function testGetAuthItem() + { + $this->assertTrue($this->auth->getAuthItem('readPost') instanceof CAuthItem); + $this->assertTrue($this->auth->getAuthItem('reader') instanceof CAuthItem); + $this->assertNull($this->auth->getAuthItem('unknown')); + } + + public function testRemoveAuthItem() + { + $this->assertTrue($this->auth->getAuthItem('updatePost') instanceof CAuthItem); + $this->assertTrue($this->auth->removeAuthItem('updatePost')); + $this->assertNull($this->auth->getAuthItem('updatePost')); + $this->assertFalse($this->auth->removeAuthItem('updatePost')); + } + + public function testChangeItemName() + { + $item=$this->auth->getAuthItem('readPost'); + $this->assertTrue($item instanceof CAuthItem); + $this->assertTrue($this->auth->hasItemChild('reader','readPost')); + $item->name='readPost2'; + $this->assertNull($this->auth->getAuthItem('readPost')); + $this->assertEquals($this->auth->getAuthItem('readPost2'),$item); + $this->assertFalse($this->auth->hasItemChild('reader','readPost')); + $this->assertTrue($this->auth->hasItemChild('reader','readPost2')); + } + + public function testAddItemChild() + { + $this->auth->addItemChild('createPost','updatePost'); + + // test adding upper level item to lower one + $this->setExpectedException('CException'); + $this->auth->addItemChild('readPost','reader'); + } + + public function testAddItemChild2() + { + // test adding inexistent items + $this->setExpectedException('CException'); + $this->assertFalse($this->auth->addItemChild('createPost2','updatePost')); + } + + public function testRemoveItemChild() + { + $this->assertTrue($this->auth->hasItemChild('reader','readPost')); + $this->assertTrue($this->auth->removeItemChild('reader','readPost')); + $this->assertFalse($this->auth->hasItemChild('reader','readPost')); + $this->assertFalse($this->auth->removeItemChild('reader','readPost')); + } + + public function testGetItemChildren() + { + $this->assertEquals(array(),$this->auth->getItemChildren('readPost')); + $children=$this->auth->getItemChildren('author'); + $this->assertEquals(3,count($children)); + $this->assertTrue(reset($children) instanceof CAuthItem); + } + + public function testAssign() + { + $auth=$this->auth->assign('createPost','new user','rule','data'); + $this->assertTrue($auth instanceof CAuthAssignment); + $this->assertEquals($auth->userId,'new user'); + $this->assertEquals($auth->itemName,'createPost'); + $this->assertEquals($auth->bizRule,'rule'); + $this->assertEquals($auth->data,'data'); + + $this->setExpectedException('CException'); + $this->auth->assign('createPost2','new user','rule','data'); + } + + public function testRevoke() + { + $this->assertTrue($this->auth->isAssigned('author','author B')); + $auth=$this->auth->getAuthAssignment('author','author B'); + $this->assertTrue($auth instanceof CAuthAssignment); + $this->assertTrue($this->auth->revoke('author','author B')); + $this->assertFalse($this->auth->isAssigned('author','author B')); + $this->assertFalse($this->auth->revoke('author','author B')); + } + + public function testGetAuthAssignments() + { + $this->auth->assign('deletePost','author B'); + $auths=$this->auth->getAuthAssignments('author B'); + $this->assertEquals(2,count($auths)); + $this->assertTrue(reset($auths) instanceof CAuthAssignment); + } + + public function testGetAuthItems() + { + $this->assertEquals(count($this->auth->getRoles()),4); + $this->assertEquals(count($this->auth->getOperations()),4); + $this->assertEquals(count($this->auth->getTasks()),1); + $this->assertEquals(count($this->auth->getAuthItems()),9); + + $this->assertEquals(count($this->auth->getAuthItems(null,'author B')),1); + $this->assertEquals(count($this->auth->getAuthItems(null,'author C')),0); + $this->assertEquals(count($this->auth->getAuthItems(CAuthItem::TYPE_ROLE,'author B')),1); + $this->assertEquals(count($this->auth->getAuthItems(CAuthItem::TYPE_OPERATION,'author B')),0); + } + + public function testClearAll() + { + $this->auth->clearAll(); + $this->assertEquals(count($this->auth->getRoles()),0); + $this->assertEquals(count($this->auth->getOperations()),0); + $this->assertEquals(count($this->auth->getTasks()),0); + $this->assertEquals(count($this->auth->getAuthItems()),0); + $this->assertEquals(count($this->auth->getAuthAssignments('author B')),0); + } + + public function testClearAuthAssignments() + { + $this->auth->clearAuthAssignments(); + $this->assertEquals(count($this->auth->getAuthAssignments('author B')),0); + } + + public function testDetectLoop() + { + $this->setExpectedException('CException'); + $this->auth->addItemChild('readPost','readPost'); + } + + public function testExecuteBizRule() + { + $this->assertTrue($this->auth->executeBizRule(null,array(),null)); + $this->assertTrue($this->auth->executeBizRule('return 1==true;',array(),null)); + $this->assertTrue($this->auth->executeBizRule('return $params[0]==$params[1];',array(1,'1'),null)); + $this->assertFalse($this->auth->executeBizRule('invalid',array(),null)); + } + + public function testCheckAccess() + { + $results=array( + 'reader A'=>array( + 'createPost'=>false, + 'readPost'=>true, + 'updatePost'=>false, + 'updateOwnPost'=>false, + 'deletePost'=>false, + ), + 'author B'=>array( + 'createPost'=>true, + 'readPost'=>true, + 'updatePost'=>true, + 'updateOwnPost'=>true, + 'deletePost'=>false, + ), + 'editor C'=>array( + 'createPost'=>false, + 'readPost'=>true, + 'updatePost'=>true, + 'updateOwnPost'=>false, + 'deletePost'=>false, + ), + 'admin D'=>array( + 'createPost'=>true, + 'readPost'=>true, + 'updatePost'=>true, + 'updateOwnPost'=>false, + 'deletePost'=>true, + ), + ); + + $params=array('authorID'=>'author B'); + + foreach(array('reader A','author B','editor C','admin D') as $user) + { + $params['userID']=$user; + foreach(array('createPost','readPost','updatePost','updateOwnPost','deletePost') as $operation) + { + $result=$this->auth->checkAccess($operation,$user,$params); + $this->assertEquals($results[$user][$operation],$result); + } + } + } + + protected function prepareData() + { + $this->auth->createOperation('createPost','create a post'); + $this->auth->createOperation('readPost','read a post'); + $this->auth->createOperation('updatePost','update a post'); + $this->auth->createOperation('deletePost','delete a post'); + + $task=$this->auth->createTask('updateOwnPost','update a post by author himself','return $params["authorID"]==$params["userID"];'); + $task->addChild('updatePost'); + + $role=$this->auth->createRole('reader'); + $role->addChild('readPost'); + + $role=$this->auth->createRole('author'); + $role->addChild('reader'); + $role->addChild('createPost'); + $role->addChild('updateOwnPost'); + + $role=$this->auth->createRole('editor'); + $role->addChild('reader'); + $role->addChild('updatePost'); + + $role=$this->auth->createRole('admin'); + $role->addChild('editor'); + $role->addChild('author'); + $role->addChild('deletePost'); + + $this->auth->assign('reader','reader A'); + $this->auth->assign('author','author B'); + $this->auth->assign('editor','editor C'); + $this->auth->assign('admin','admin D'); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CDbAuthManagerTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CDbAuthManagerTest.php new file mode 100644 index 0000000..7e76d79 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CDbAuthManagerTest.php @@ -0,0 +1,45 @@ +<?php + +require_once(dirname(__FILE__).'/AuthManagerTestBase.php'); + +class CDbAuthManagerTest extends AuthManagerTestBase +{ + private $db; + + public function setUp() + { + if(!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) + $this->markTestSkipped('PDO and PostgreSQL extensions are required.'); + + $schemaFile=realpath(Yii::getPathOfAlias('system.web.auth.schema-pgsql').'.sql'); + + $this->db=new CDbConnection('pgsql:host=localhost;dbname=yii','test','test'); + try + { + $this->db->active=true; + } + catch(Exception $e) + { + $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for PostgreSQL test case."); + } + + $sqls=preg_replace('/\/\*.*\*\//s', '', file_get_contents($schemaFile)); + foreach(explode(';',$sqls) as $sql) + { + if(trim($sql)!=='') + $this->db->createCommand($sql)->execute(); + } + $this->db->active=false; + + $this->auth=new CDbAuthManager; + $this->auth->db=$this->db; + $this->auth->init(); + $this->prepareData(); + } + + public function tearDown() + { + if($this->db) + $this->db->active=false; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CPhpAuthManagerTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CPhpAuthManagerTest.php new file mode 100644 index 0000000..eeeb38b --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CPhpAuthManagerTest.php @@ -0,0 +1,29 @@ +<?php + +require_once(dirname(__FILE__).'/AuthManagerTestBase.php'); + +class CPhpAuthManagerTest extends AuthManagerTestBase +{ + public function setUp() + { + $authFile=Yii::app()->getRuntimePath().'/CPhpAuthManagerTest_auth.php'; + @unlink($authFile); + $this->auth=new CPhpAuthManager; + $this->auth->authFile=$authFile; + $this->auth->init(); + $this->prepareData(); + } + + public function tearDown() + { + @unlink($this->auth->authFile); + } + + public function testSaveLoad() + { + $this->auth->save(); + $this->auth->clearAll(); + $this->auth->load(); + $this->testCheckAccess(); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CWebUserTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CWebUserTest.php new file mode 100644 index 0000000..3cbd6bc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/auth/CWebUserTest.php @@ -0,0 +1,77 @@ +<?php + +/** + * Test for CWebUser + * + * tests are running in separate process to allow session management to work properly + */ +class CWebUserTest extends CTestCase +{ + public function setUp() + { + Yii::app()->setComponent('authManager', new CPhpAuthManager()); + + /** @var CPhpAuthManager $auth */ + $auth = Yii::app()->authManager; + $auth->createOperation('createPost'); + $auth->createOperation('deletePost'); + $auth->assign('createPost', 'admin'); + } + + public function tearDown() + { + Yii::app()->session->destroy(); + Yii::app()->setComponent('authManager', null); + } + + public function booleanProvider() + { + return array(array(true), array(false)); + } + + /** + * @runInSeparateProcess + * @outputBuffering enabled + * @dataProvider booleanProvider + */ + public function testLoginLogout($destroySession) + { + $identity = new CUserIdentity('testUser', 'testPassword'); + + $user = new CWebUser(); + $user->init(); + + // be guest before login + $this->assertTrue($user->isGuest); + // do a login + $this->assertTrue($user->login($identity)); + // don't be guest after login + $this->assertFalse($user->isGuest); + $this->assertEquals('testUser', $user->getId()); + $this->assertEquals('testUser', $user->getName()); + + $user->logout($destroySession); + + // be guest after logout + $this->assertNull($user->getId()); + $this->assertEquals($user->guestName, $user->getName()); + } + + /** + * @runInSeparateProcess + * @outputBuffering enabled + */ + public function testCheckAccess() + { + $identity = new CUserIdentity('admin', 'admin'); + Yii::app()->user->login($identity); + + $this->assertTrue(Yii::app()->user->checkAccess('createPost')); + $this->assertFalse(Yii::app()->user->checkAccess('deletePost')); + + Yii::app()->user->logout(); + + $this->assertFalse(Yii::app()->user->checkAccess('createPost')); + $this->assertFalse(Yii::app()->user->checkAccess('deletePost')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/SoapController.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/SoapController.php new file mode 100644 index 0000000..0d3a306 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/SoapController.php @@ -0,0 +1,105 @@ +<?php +/** +* Fake SOAP controller for unit tests +* Handle SOAP client requests & generate WSDL. +* +* NOTE: +* This is a fake controller used only for generating WSDL files. +* Some functionlities are here as an example and may not be fully functional. +* +* Sample call: +* $client = new SoapClient('http://1.2.3.4/index.php?r=soap'); +* $response = $client->connect(); +*/ +class SoapController extends CController implements IWebServiceProvider +{ + const LOGNAME = 'soap'; + + public function actions(){ + return array( + // remap default action "index" to be a SOAP action + 'index'=>array( + 'class'=>'WebServiceAction', + 'classMap' => array( + 'SoapPovCalculationInput', 'SoapPovCalculationOutput', + ), + ), + ); + } + + /** + * Preprocess actions before calling SOAP action. + * This method must implement interface's abstract method. + * @param mixed $service + */ + public function beforeWebMethod($service) { + // do whatever stuff before executing the action ... + return true; + } + + /** + * Postprocess actions after SOAP action executed. + * This method must implement interface's abstract method. + * @param mixed $service + */ + public function afterWebMethod($service) { + // do whatever stuff after executing the action ... + return true; + } + + /** + * Return TRUE if the SOAP user is authorized. + */ + protected function isAuthorized($user, $passwordHashed, $action) { + // load allowed users.. + $users = array('tester123' => 'passwordHashed123'); + + if (isset($users[$user]) && $passwordHashed == $users[$user]) { + /** + * @var CHttpRequest + */ + $request = Yii::app()->request; + $url = $request->getHostInfo() . $request->getUrl(); + Log::write('['.$user.'] => ['.$action.'] Granted access via ['.$url.']', self::LOGNAME); + return true; + } + + Log::write('['.$user.'] => ['.$action.'] Failed login with ['.$passwordHashed.']', self::LOGNAME); + return false; + } + + /** + * Check connection to soap server and return current timestamp on success. No authorization required - used simply for seting up the connection via proxy, firewall, http authentication etc... + * @return string Current timestamp dd.mm.YYYY HH:ii:ss + * @soap + */ + public function connect(){ + $request = Yii::app()->request; + $url = $request->getHostInfo() . $request->getUrl(); + Log::write( '['.__FUNCTION__.'] OK - Connection succesfull via ['.$url.']', self::LOGNAME); + return 'OK - connection succesfull at ['.date('d.m.Y H:i:s').']'; + } + + /** + * Return some calculation results for supplied input parameters. + * + * @param string Authorized login username + * @param string Authorized login password + * @param SoapPovCalculationInput Calculation input object + * @return SoapPovCalculationOutput Calculation output object + * @soap + */ + public function calculatePov($user, $password, $input) { + + if(!$this->isAuthorized($user, $password, __FUNCTION__)){ + throw new SoapFault(null, 'Unauthorized access ['.__FUNCTION__.']!'); + } + + $calc = new SoapPovCalculation($input); + $calc->setPartner($user); + $output = $calc->calculate(); + + return $output; + } + +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/admin/index.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/admin/index.php new file mode 100644 index 0000000..e69de29 diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/article.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/article.php new file mode 100644 index 0000000..e69de29 diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/home2.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/home2.php new file mode 100644 index 0000000..e69de29 diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/post.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/controllers/post.php new file mode 100644 index 0000000..e69de29 diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CHtml/providerValue.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CHtml/providerValue.php new file mode 100644 index 0000000..303c15c --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CHtml/providerValue.php @@ -0,0 +1,11 @@ +<?php + +// Following array is being used in CHtmlTest::providerValue() method, but it's moved here into separate file because +// PHP 5.2 cannot parse lambda function declarations, even if such code won't be executed at all. This is the only +// workaround to this PHP peculiarity (there are no opportunities to control PHP parser statically a.k.a. +// "compile"-time control). + +return array( + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),function($model) { return $model['k2']; },null,'v2'), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),function($model) { return $model->k2; },null,'v2'), +); diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CHtmlTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CHtmlTest.php new file mode 100644 index 0000000..70bfb13 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CHtmlTest.php @@ -0,0 +1,1156 @@ +<?php + +class CHtmlTest extends CTestCase +{ + public function setUp() + { + // clean up any possible garbage in global clientScript app component + Yii::app()->clientScript->reset(); + + // reset CHtml ID counter + CHtml::$count=0; + + Yii::app()->request->baseUrl=null; // reset so that it can be determined based on scriptUrl + Yii::app()->request->scriptUrl='/bootstrap.php'; + } + + public function tearDown() + { + // do not keep any garbage in global clientScript app component + Yii::app()->clientScript->reset(); + } + + /* HTML characters encode/decode tests */ + + public static function providerEncodeArray() + { + return array( + array( array('lessThanExpression'=>'4 < 9'), array('lessThanExpression'=>'4 < 9') ), + array( array(array('lessThanExpression'=>'4 < 9')), array(array('lessThanExpression'=>'4 < 9')) ), + array( array(array('lessThanExpression'=>'4 < 9'), 'greaterThanExpression'=>'4 > 9'), array(array('lessThanExpression'=>'4 < 9'), 'greaterThanExpression'=>'4 > 9') ) + ); + } + + /** + * @dataProvider providerEncodeArray + * + * @param type $data + * @param type $assertion + */ + public function testEncodeArray($data, $assertion) + { + $this->assertEquals($assertion, CHtml::encodeArray($data)); + } + + /* Javascript generator tests */ + + public static function providerAjax() + { + return array( + array(array("url" => "index"), "jQuery.ajax({'url':'index','cache':false});"), + array(array("url" => "index", "success" => "function() { this.alert(\"HI\"); }"), "jQuery.ajax({'url':'index','success':function() { this.alert(\"HI\"); },'cache':false});"), + array(array("async" => true, "success" => "function() { this.alert(\"HI\"); }"), "jQuery.ajax({'async':true,'success':function() { this.alert(\"HI\"); },'url':location.href,'cache':false});"), + array(array("update" =>"#my-div", "success" => "function() { this.alert(\"HI\"); }"), "jQuery.ajax({'success':function() { this.alert(\"HI\"); },'url':location.href,'cache':false});"), + array(array("update" =>"#my-div"), "jQuery.ajax({'url':location.href,'cache':false,'success':function(html){jQuery(\"#my-div\").html(html)}});"), + array(array("replace" =>"#my-div", "success" => "function() { this.alert(\"HI\"); }"), "jQuery.ajax({'success':function() { this.alert(\"HI\"); },'url':location.href,'cache':false});"), + array(array("replace" =>"#my-div"), "jQuery.ajax({'url':location.href,'cache':false,'success':function(html){jQuery(\"#my-div\").replaceWith(html)}});") + ); + } + + /** + * @dataProvider providerAjax + * + * @param type $options + * @param type $assertion + */ + public function testAjax($options, $assertion) + { + $this->assertEquals($assertion, CHtml::ajax($options)); + } + + /* DOM element generated from model attribute tests */ + + public static function providerActiveDOMElements() + { + return array( + array(new CHtmlTestModel(array('attr1'=>true)), 'attr1', array(), '<input id="ytCHtmlTestModel_attr1" type="hidden" value="0" name="CHtmlTestModel[attr1]" /><input name="CHtmlTestModel[attr1]" id="CHtmlTestModel_attr1" value="1" type="checkbox" />'), + array(new CHtmlTestModel(array('attr1'=>false)), 'attr1', array(), '<input id="ytCHtmlTestModel_attr1" type="hidden" value="0" name="CHtmlTestModel[attr1]" /><input name="CHtmlTestModel[attr1]" id="CHtmlTestModel_attr1" value="1" type="checkbox" />') + ); + } + + /** + * @dataProvider providerActiveDOMElements + * + * @param string $action + * @param string $method + * @param array $htmlOptions + * @param string $assertion + */ + public function testActiveCheckbox($model,$attribute,$htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::activeCheckBox($model,$attribute,$htmlOptions)); + } + + /* Static DOM element generator tests */ + + public static function providerBeginForm() + { + return array( + array("index", "get", array(), '<form action="index" method="get">'), + array("index", "post", array(), '<form action="index" method="post">'), + array("index?myFirstParam=3&mySecondParam=true", "get", array(), +"<form action=\"index?myFirstParam=3&mySecondParam=true\" method=\"get\">\n". +"<div style=\"display:none\"><input type=\"hidden\" value=\"3\" name=\"myFirstParam\" />\n". +"<input type=\"hidden\" value=\"true\" name=\"mySecondParam\" /></div>"), + + ); + } + + /** + * @dataProvider providerBeginForm + * + * @param string $action + * @param string $method + * @param array $htmlOptions + * @param string $assertion + */ + public function testBeginForm($action, $method, $htmlOptions, $assertion) + { + /* TODO - Steven Wexler - 3/5/11 - Mock out static methods in this function when CHtml leverages late static method binding + * because PHPUnit. This is only possible Yii supports only >= PHP 5.3 - */ + $this->assertEquals($assertion, CHtml::beginForm($action, $method, $htmlOptions)); + $this->assertEquals($assertion, CHtml::form($action, $method, $htmlOptions)); + } + + public static function providerTextArea() + { + return array( + array("textareaone", '', array(), "<textarea name=\"textareaone\" id=\"textareaone\"></textarea>"), + array("textareaone", '', array("id"=>"MyAwesomeTextArea", "dog"=>"Lassie", "class"=>"colorful bright"), "<textarea id=\"MyAwesomeTextArea\" dog=\"Lassie\" class=\"colorful bright\" name=\"textareaone\"></textarea>"), + array("textareaone", '', array("id"=>false), "<textarea name=\"textareaone\"></textarea>"), + ); + } + + /** + * @dataProvider providerTextArea + * + * @param string $name + * @param string $value + * @param array $htmlOptions + * @param string $assertion + */ + public function testTextArea($name, $value, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::textArea($name, $value, $htmlOptions)); + } + + public function providerOpenTag() + { + return array( + array('div', array(), '<div>'), + array('h1', array('id'=>'title', 'class'=>'red bold'), '<h1 id="title" class="red bold">'), + array('ns:tag', array('attr1'=>'attr1value1 attr1value2'), '<ns:tag attr1="attr1value1 attr1value2">'), + array('option', array('checked'=>true, 'disabled'=>false, 'defer'=>true), '<option checked="checked" defer="defer">'), + array('another-tag', array('some-attr'=>'<>/\\<&', 'encode'=>true), '<another-tag some-attr="<>/\<&">'), + array('tag', array('attr-no-encode'=>'<&', 'encode'=>false), '<tag attr-no-encode="<&">'), + ); + } + + /** + * @dataProvider providerOpenTag + * + * @param string $tag + * @param string $htmlOptions + * @param string $assertion + */ + public function testOpenTag($tag, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::openTag($tag, $htmlOptions)); + } + + public static function providerCloseTag() + { + return array( + array('div', '</div>'), + array('h1', '</h1>'), + array('ns:tag', '</ns:tag>'), + array('minus-tag', '</minus-tag>'), + ); + } + + /** + * @dataProvider providerCloseTag + * + * @param string $tag + * @param string $assertion + */ + public function testCloseTag($tag, $assertion) + { + $this->assertEquals($assertion, CHtml::closeTag($tag)); + } + + public static function providerCdata() + { + return array( + array('cdata-content', '<![CDATA[cdata-content]]>'), + array('123321', '<![CDATA[123321]]>'), + ); + } + + /** + * @dataProvider providerCdata + * + * @param string $data + * @param string $assertion + */ + public function testCdata($data, $assertion) + { + $this->assertEquals($assertion, CHtml::cdata($data)); + } + + public function providerMetaTag() + { + return array( + array('simple-meta-tag', null, null, array(), + '<meta content="simple-meta-tag" />'), + array('test-name-attr', 'random-name', null, array(), + '<meta name="random-name" content="test-name-attr" />'), + array('text/html; charset=UTF-8', null, 'Content-Type', array(), + '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'), + array('test-attrs', null, null, array('xhtml-invalid-attr'=>'attr-value'), + '<meta xhtml-invalid-attr="attr-value" content="test-attrs" />'), + array('complex-test', 'testing-name', 'Content-Type', array('attr1'=>'value2'), + '<meta attr1="value2" name="testing-name" http-equiv="Content-Type" content="complex-test" />'), + ); + } + + /** + * @dataProvider providerMetaTag + * + * @param string $content + * @param string $name + * @param string $httpEquiv + * @param array $options + * @param string $assertion + */ + public function testMetaTag($content, $name, $httpEquiv, $options, $assertion) + { + $this->assertEquals($assertion, CHtml::metaTag($content, $name, $httpEquiv, $options)); + } + + public function providerLinkTag() + { + return array( + array(null, null, null, null, array(), '<link />'), + array('stylesheet', null, null, null, array(), '<link rel="stylesheet" />'), + array(null, 'text/css', null, null, array(), '<link type="text/css" />'), + array(null, null, '/css/style.css', null, array(), '<link href="/css/style.css" />'), + array(null, null, null, 'screen', array(), '<link media="screen" />'), + array(null, null, null, null, array('attr'=>'value'), '<link attr="value" />'), + array('stylesheet', 'text/css', '/css/style.css', 'screen', array('attr'=>'value'), + '<link attr="value" rel="stylesheet" type="text/css" href="/css/style.css" media="screen" />'), + ); + } + + /** + * @dataProvider providerLinkTag + * + * @param string $relation + * @param string $type + * @param string $href + * @param string $media + * @param array $options + * @param string $assertion + */ + public function testLinkTag($relation, $type, $href, $media, $options, $assertion) + { + $this->assertEquals($assertion, CHtml::linkTag($relation, $type, $href, $media, $options)); + } + + public static function providerCss() + { + return array( + array('h1{font-size:20px;line-height:26px;}', '', + "<style type=\"text/css\">\n/*<![CDATA[*/\nh1{font-size:20px;line-height:26px;}\n/*]]>*/\n</style>"), + array('h2{font-size:16px;line-height:22px;}', 'screen', + "<style type=\"text/css\" media=\"screen\">\n/*<![CDATA[*/\nh2{font-size:16px;line-height:22px;}\n/*]]>*/\n</style>"), + ); + } + + /** + * @dataProvider providerCss + * + * @param string $text + * @param string $media + * @param string $assertion + */ + public function testCss($text, $media, $assertion) + { + $this->assertEquals($assertion, CHtml::css($text, $media)); + } + + public static function providerCssFile() + { + return array( + array('/css/style.css?a=1&b=2', '', '<link rel="stylesheet" type="text/css" href="/css/style.css?a=1&b=2" />'), + array('/css/style.css?c=3&d=4', 'screen', '<link rel="stylesheet" type="text/css" href="/css/style.css?c=3&d=4" media="screen" />'), + ); + } + + /** + * @dataProvider providerCssFile + * + * @param string $url + * @param string $media + * @param string $assertion + */ + public function testCssFile($url, $media, $assertion) + { + $this->assertEquals($assertion, CHtml::cssFile($url, $media)); + } + + public static function providerScript() + { + return array( + array('var a = 10;', "<script type=\"text/javascript\">\n/*<![CDATA[*/\nvar a = 10;\n/*]]>*/\n</script>"), + array("\t(function() { var x = 100; })();\n\tvar y = 200;", + "<script type=\"text/javascript\">\n/*<![CDATA[*/\n\t(function() { var x = 100; })();\n\tvar y = 200;\n/*]]>*/\n</script>"), + ); + } + + /** + * @dataProvider providerScript + * + * @param string $text + * @param string $assertion + */ + public function testScript($text, $assertion) + { + $this->assertEquals($assertion, CHtml::script($text)); + } + + public static function providerScriptWithHtmlOptions() + { + return array( + array( + 'var a = 10;', + array('defer'=>true), + "<script type=\"text/javascript\" defer=\"defer\">\n/*<![CDATA[*/\nvar a = 10;\n/*]]>*/\n</script>" + ), + array( + 'var a = 10;', + array('async'=>true), + "<script type=\"text/javascript\" async=\"async\">\n/*<![CDATA[*/\nvar a = 10;\n/*]]>*/\n</script>" + ), + ); + } + + /** + * @depends testScript + * @dataProvider providerScriptWithHtmlOptions + * + * @param string $text + * @param array $htmlOptions + * @param string $assertion + */ + public function testScriptWithHtmlOptions($text, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::script($text,$htmlOptions)); + } + + public static function providerScriptFile() + { + return array( + array('/js/main.js?a=2&b=4', '<script type="text/javascript" src="/js/main.js?a=2&b=4"></script>'), + array('http://company.com/get-user-by-name?name=ВаÑилий&lang=ru', + '<script type="text/javascript" src="http://company.com/get-user-by-name?name=ВаÑилий&lang=ru"></script>'), + ); + } + + /** + * @dataProvider providerScriptFile + * + * @param string $text + * @param string $assertion + */ + public function testScriptFile($text, $assertion) + { + $this->assertEquals($assertion, CHtml::scriptFile($text)); + } + + public static function providerScriptFileWithHtmlOptions() + { + return array( + array( + '/js/main.js?a=2&b=4', + array('defer'=>true), + '<script type="text/javascript" src="/js/main.js?a=2&b=4" defer="defer"></script>' + ), + array( + '/js/main.js?a=2&b=4', + array('async'=>true), + '<script type="text/javascript" src="/js/main.js?a=2&b=4" async="async"></script>' + ), + array( + '/js/main.js?a=2&b=4', + array('onload'=>"some_js_function();"), + '<script type="text/javascript" src="/js/main.js?a=2&b=4" onload="some_js_function();"></script>' + ), + ); + } + + /** + * @depends testScriptFile + * @dataProvider providerScriptFileWithHtmlOptions + * + * @param string $text + * @param array $htmlOptions + * @param string $assertion + */ + public function testScriptFileWithHtmlOptions($text, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::scriptFile($text, $htmlOptions)); + } + + public function testEndForm() + { + $this->assertEquals('</form>', CHtml::endForm()); + } + + public function testActiveId() + { + $testModel=new CHtmlTestModel(); + $this->assertEquals('CHtmlTestModel_attr1', CHtml::activeId($testModel, 'attr1')); + $this->assertEquals('CHtmlTestModel_attr2', CHtml::activeId($testModel, 'attr2')); + $this->assertEquals('CHtmlTestModel_attr3', CHtml::activeId($testModel, 'attr3')); + $this->assertEquals('CHtmlTestModel_attr4', CHtml::activeId($testModel, 'attr4')); + } + + public function testActiveName() + { + $testModel=new CHtmlTestModel(); + $this->assertEquals('CHtmlTestModel[attr1]', CHtml::activeName($testModel, 'attr1')); + $this->assertEquals('CHtmlTestModel[attr2]', CHtml::activeName($testModel, 'attr2')); + $this->assertEquals('CHtmlTestModel[attr3]', CHtml::activeName($testModel, 'attr3')); + $this->assertEquals('CHtmlTestModel[attr4]', CHtml::activeName($testModel, 'attr4')); + } + + public static function providerGetIdByName() + { + return array( + array('ContactForm[name]', 'ContactForm_name'), + array('Order[name][first]', 'Order_name_first'), + array('Order[name][last]', 'Order_name_last'), + array('Recipe[photo][]', 'Recipe_photo'), + array('Request title', 'Request_title'), + ); + } + + /** + * @dataProvider providerGetIdByName + * + * @param string $text + * @param string $assertion + */ + public function testGetIdByName($text, $assertion) + { + $this->assertEquals($assertion, CHtml::getIdByName($text)); + } + + public function testResolveName() + { + $testModel=new CHtmlTestFormModel(); + + $attrName='stringAttr'; + $this->assertEquals('CHtmlTestFormModel[stringAttr]', CHtml::resolveName($testModel, $attrName)); + $this->assertEquals('stringAttr', $attrName); + + $attrName='arrayAttr[k1]'; + $this->assertEquals('CHtmlTestFormModel[arrayAttr][k1]', CHtml::resolveName($testModel, $attrName)); + $this->assertEquals('arrayAttr[k1]', $attrName); + + $attrName='arrayAttr[k3][k5]'; + $this->assertEquals('CHtmlTestFormModel[arrayAttr][k3][k5]', CHtml::resolveName($testModel, $attrName)); + $this->assertEquals('arrayAttr[k3][k5]', $attrName); + + $attrName='[k3][k4]arrayAttr'; + $this->assertEquals('CHtmlTestFormModel[k3][k4][arrayAttr]', CHtml::resolveName($testModel, $attrName)); + $this->assertEquals('arrayAttr', $attrName); + + $attrName='[k3]arrayAttr[k4]'; + $this->assertEquals('CHtmlTestFormModel[k3][arrayAttr][k4]', CHtml::resolveName($testModel, $attrName)); + $this->assertEquals('arrayAttr[k4]', $attrName); + + // next two asserts gives 100% code coverage of the CHtml::resolveName() method + // otherwise penultimate line (last closing curly bracket) of the CHtml::resolveName() will not be unit tested + $attrName='[k3'; + $this->assertEquals('CHtmlTestFormModel[[k3]', CHtml::resolveName($testModel, $attrName)); + $this->assertEquals('[k3', $attrName); + } + + public function testResolveValue() + { + $testModel=new CHtmlTestFormModel(); + + $this->assertEquals('stringAttrValue', CHtml::resolveValue($testModel, 'stringAttr')); + $this->assertEquals('v1', CHtml::resolveValue($testModel, 'arrayAttr[k1]')); + $this->assertEquals('v2', CHtml::resolveValue($testModel, 'arrayAttr[k2]')); + $this->assertEquals($testModel->arrayAttr['k3'], CHtml::resolveValue($testModel, 'arrayAttr[k3]')); + $this->assertEquals('v4', CHtml::resolveValue($testModel, 'arrayAttr[k3][k4]')); + $this->assertEquals('v5', CHtml::resolveValue($testModel, 'arrayAttr[k3][k5]')); + $this->assertEquals('v6', CHtml::resolveValue($testModel, 'arrayAttr[k6]')); + + $this->assertNull(CHtml::resolveValue($testModel, 'arrayAttr[k7]')); + $this->assertNull(CHtml::resolveValue($testModel, 'arrayAttr[k7][k8]')); + + $this->assertEquals($testModel->arrayAttr, CHtml::resolveValue($testModel, '[ignored-part]arrayAttr')); + $this->assertEquals('v1', CHtml::resolveValue($testModel, '[ignored-part]arrayAttr[k1]')); + $this->assertEquals('v4', CHtml::resolveValue($testModel, '[ignore-this]arrayAttr[k3][k4]')); + } + + public function providerValue() + { + $result=array( + // $model is array + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),'k1',null,'v1'), + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),'k2',null,'v2'), + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),'k3',null,null), + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),'k3','defaultValue','defaultValue'), + + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),0,null,'v3'), + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),1,null,'v4'), + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),2,null,null), + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),2,'defaultValue','defaultValue'), + + // $model is stdClass + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),'k1',null,'v1'), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),'k2',null,'v2'), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),'k3',null,null), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),'k3','defaultValue','defaultValue'), + + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),0,null,null), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),1,null,null), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),2,null,null), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),2,'defaultValue','defaultValue'), + + // static method + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),array('CHtmlTest','helperTestValue'),null,'v2'), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),array('CHtmlTest','helperTestValue'),null,'v2'), + + // create_function is not supported by CHtml::value(), we're just testing this feature/property + array(array('k1'=>'v1','k2'=>'v2','v3','v4'),create_function('$model','return $model["k2"];'),null,null), + array((object)array('k1'=>'v1','k2'=>'v2','v3','v4'),create_function('$model','return $model->k2;'),null,null), + + // standard PHP functions should not be treated as callables + array(array('array_filter'=>'array_filter','sort'=>'sort'),'sort',null,'sort'), + array(array('array_filter'=>'array_filter','sort'=>'sort'),'array_map','defaultValue','defaultValue'), + array((object)array('array_filter'=>'array_filter','sort'=>'sort'),'sort',null,'sort'), + array((object)array('array_filter'=>'array_filter','sort'=>'sort'),'array_map','defaultValue','defaultValue'), + + // dot access, array + array(array('k1'=>array('k2'=>array('k3'=>'v3')),array('v1','k4'=>'v4')),'k1.k2.k3',null,'v3'), + array(array('k1'=>array('k2'=>array('k3'=>'v3')),array('v1','k4'=>'v4')),'0.0',null,'v1'), + array(array('k1'=>array('k2'=>array('k3'=>'v3')),array('v1','k4'=>'v4')),'0.k4',null,'v4'), + array(array('k1'=>array('k2'=>array('k3'=>'v3')),array('v1','k4'=>'v4')),'0.1',null,null), + + // dot access, object + array((object)array('k1'=>array('k2'=>array('k3'=>'v3')),array('v1','k4'=>'v4')),'k1.k2.k3',null,'v3'), + array((object)array('k1'=>array('k2'=>array('k3'=>'v3')),array('v1','k4'=>'v4')),'0.0',null,null), + array((object)array('k1'=>array('k2'=>array('k3'=>'v3')),array('v1','k4'=>'v4')),'0.k4',null,null), + array((object)array('k1'=>array('k2'=>array('k3'=>'v3')),array('v1','k4'=>'v4')),'0.1',null,null), + + // $attribute parameter is: + // 1. null or empty string + // 2. not "0" string, 0 integer or 0.0 double/float + // 3. empty array doesn't make sense + array(array('v1'),null,'defaultValue','defaultValue'), + array(array('v1'),"",'defaultValue','defaultValue'), + array(array('v1'),"0",'defaultValue','v1'), + array(array('v1'),0,'defaultValue','v1'), + array(array('v1'),0.0,'defaultValue','v1'), + ); + if(class_exists('Closure',false)) + { + // anonymous function + $result=array_merge($result,require(dirname(__FILE__).'/CHtml/providerValue.php')); + } + return $result; + } + + /** + * @dataProvider providerValue + * + * @param array|stdClass $model + * @param integer|double|string $attribute + * @param mixed $defaultValue + * @param string $assertion + */ + public function testValue($model, $attribute, $defaultValue, $assertion) + { + $this->assertEquals($assertion, CHtml::value($model, $attribute, $defaultValue)); + } + + /** + * Helper method for {@link testValue()} and {@link providerValue()} methods. + */ + public static function helperTestValue($model) + { + return is_array($model) ? $model['k2'] : $model->k2; + } + + public static function providerPageStateField() + { + return array( + array('testing-value', '<input type="hidden" name="'.CController::STATE_INPUT_NAME.'" value="testing-value" />'), + array('another-testing&value', '<input type="hidden" name="'.CController::STATE_INPUT_NAME.'" value="another-testing&value" />'), + ); + } + + /** + * @dataProvider providerPageStateField + * + * @param string $value + * @param string $assertion + */ + public function testPageStateField($value, $assertion) + { + $this->assertEquals($assertion, CHtml::pageStateField($value)); + } + + public static function providerEncodeDecode() + { + return array( + array( + '<h1 class="header" attr=\'value\'>Text header</h1>', + '<h1 class="header" attr='value'>Text header</h1>', + ), + array( + '<p>testing & text</p>', + '<p>testing & text</p>', + ), + ); + } + + /** + * @dataProvider providerEncodeDecode + * + * @param string $text + * @param string $assertion + */ + public function testEncode($text, $assertion) + { + $this->assertEquals($assertion, CHtml::encode($text)); + } + + /** + * @dataProvider providerEncodeDecode + * + * @param string $assertion + * @param string $text + */ + public function testDecode($assertion, $text) + { + $this->assertEquals($assertion, CHtml::decode($text)); + } + + public static function providerRefresh() + { + return array( + array( + 10, + 'http://yiiframework.com/', + '<meta http-equiv="refresh" content="10;url=http://yiiframework.com/" />'."\n", + ), + array( + 15, + array('site/index'), + '<meta http-equiv="refresh" content="15;url=/bootstrap.php?r=site/index" />'."\n", + ), + ); + } + + /** + * @dataProvider providerRefresh + * + * @param $seconds + * @param $url + * @param $assertion + */ + public function testRefresh($seconds, $url, $assertion) + { + // this adds element to the CClientScript::$metaTags + CHtml::refresh($seconds, $url); + + // now render html head with registered meta tags + $output=''; + Yii::app()->clientScript->renderHead($output); + + // and test it now + $this->assertEquals($assertion, $output); + } + + public static function providerStatefulForm() + { + // we should keep in mind that CHtml::statefulForm() calls CHtml::beginForm() internally + // so we can make expected assertion value more readable by using CHtml::beginForm() because + // we are testing stateful feature of the CHtml::statefulForm(), not <form> tag generation + // same true for CHtml::pageStateField - it is already tested in another method + return array( + array( + array('site/index'), + 'post', + array(), + CHtml::form(array('site/index'), 'post', array())."\n".'<div style="display:none">'.CHtml::pageStateField('').'</div>' + ), + array( + '/some-static/url', + 'get', + array('test-attr'=>'test-value'), + CHtml::form('/some-static/url', 'get', array('test-attr'=>'test-value'))."\n".'<div style="display:none">'.CHtml::pageStateField('').'</div>' + ), + ); + } + + /** + * @dataProvider providerStatefulForm + * + * @param string $action + * @param string $method + * @param array $htmlOptions + * @param string $assertion + */ + public function testStatefulForm($action, $method, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::statefulForm($action, $method, $htmlOptions)); + } + + public static function providerMailto() + { + return array( + array( + 'Drop me a line! ;-)', + 'admin@example.com', + array('class'=>'mail-to-admin'), + '<a class="mail-to-admin" href="mailto:admin@example.com">Drop me a line! ;-)</a>', + ), + array( + 'Contact me', + 'foo@bar.baz', + array(), + '<a href="mailto:foo@bar.baz">Contact me</a>', + ), + array( + 'boss@acme.com', + '', + array(), + '<a href="mailto:boss@acme.com">boss@acme.com</a>', + ), + ); + } + + /** + * @dataProvider providerMailto + * + * @param string $text + * @param string $email + * @param array $htmlOptions + * @param string $assertion + */ + public function testMailto($text, $email, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::mailto($text, $email, $htmlOptions)); + } + + public static function providerImage() + { + return array( + array('/images/logo.png', 'YiiSoft, LLC', array(), '<img src="/images/logo.png" alt="YiiSoft, LLC" />'), + array('/img/test.jpg', '', array('class'=>'test-img'), '<img class="test-img" src="/img/test.jpg" alt="" />'), + ); + } + + /** + * @dataProvider providerImage + * + * @param string $src + * @param string $alt + * @param array $htmlOptions + * @param string $assertion + */ + public function testImage($src, $alt, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::image($src, $alt, $htmlOptions)); + } + + public function providerActiveLabel() + { + return array( + array(false, 'userName', array(), '<label for="CHtmlTestActiveModel_userName">User Name</label>'), + array(false, 'userName', array('for'=>'someTestingInput'), '<label for="someTestingInput">User Name</label>'), + array(false, 'userName', array('label'=>'Custom Label'), '<label for="CHtmlTestActiveModel_userName">Custom Label</label>'), + array(false, 'userName', array('label'=>false), ''), + array(true, 'userName', array(), '<label class="error" for="CHtmlTestActiveModel_userName">User Name</label>'), + array(true, 'userName', array('for'=>'someTestingInput'), '<label class="error" for="someTestingInput">User Name</label>'), + array(true, 'firstName', array('label'=>'Custom Label'), '<label for="CHtmlTestActiveModel_firstName">Custom Label</label>'), + array(true, 'userName', array('label'=>false), ''), + array(false, '[1]userName', array('for'=>'customFor'), '<label for="customFor">User Name</label>'), + ); + } + + /** + * @dataProvider providerActiveLabel + * + * @param boolean $validate + * @param string $attribute + * @param array $htmlOptions + * @param string $assertion + */ + public function testActiveLabel($validate, $attribute, $htmlOptions, $assertion) + { + $model=new CHtmlTestActiveModel(); + if($validate) + $model->validate(); + $this->assertEquals($assertion, CHtml::activeLabel($model, $attribute, $htmlOptions)); + } + + public function providerActiveLabelEx() + { + return array( + array(false, 'firstName', array(), '<label for="CHtmlTestActiveModel_firstName">First Name</label>'), + array(false, 'firstName', array('for'=>'someTestingInput'), '<label for="someTestingInput">First Name</label>'), + array(false, 'userName', array('label'=>'Custom Label'), '<label for="CHtmlTestActiveModel_userName" class="required">Custom Label <span class="required">*</span></label>'), + array(false, 'userName', array('label'=>false), ''), + array(true, 'userName', array(), '<label class="error required" for="CHtmlTestActiveModel_userName">User Name <span class="required">*</span></label>'), + array(true, 'userName', array('for'=>'someTestingInput'), '<label class="error required" for="someTestingInput">User Name <span class="required">*</span></label>'), + array(true, 'firstName', array('label'=>'Custom Label'), '<label for="CHtmlTestActiveModel_firstName">Custom Label</label>'), + array(true, 'firstName', array('label'=>false), ''), + ); + } + + /** + * @dataProvider providerActiveLabelEx + * + * @param boolean $addErrors + * @param string $attribute + * @param array $htmlOptions + * @param string $validate + */ + public function testActiveLabelEx($validate, $attribute, $htmlOptions, $assertion) + { + $model=new CHtmlTestActiveModel(); + if($validate) + $model->validate(); + $this->assertEquals($assertion, CHtml::activeLabelEx($model, $attribute, $htmlOptions)); + } + + public function providerActiveTextField() + { + return array( + array(false, 'userName', array('class'=>'user-name-field'), + '<input class="user-name-field" name="CHtmlTestActiveModel[userName]" id="CHtmlTestActiveModel_userName" type="text" />'), + array(true, 'userName', array('class'=>'user-name-field'), + '<input class="user-name-field error" name="CHtmlTestActiveModel[userName]" id="CHtmlTestActiveModel_userName" type="text" />'), + array(false, 'firstName', array('class'=>'first-name-field'), + '<input class="first-name-field" name="CHtmlTestActiveModel[firstName]" id="CHtmlTestActiveModel_firstName" type="text" />'), + array(true, 'firstName', array('class'=>'first-name-field'), + '<input class="first-name-field" name="CHtmlTestActiveModel[firstName]" id="CHtmlTestActiveModel_firstName" type="text" />'), + ); + } + + /** + * @dataProvider providerActiveTextField + * + * @param boolean $validate + * @param string $attribute + * @param array $htmlOptions + * @param string $assertion + */ + public function testActiveTextField($validate, $attribute, $htmlOptions, $assertion) + { + $model=new CHtmlTestActiveModel(); + if($validate) + $model->validate(); + $this->assertEquals($assertion, CHtml::activeTextField($model, $attribute, $htmlOptions)); + } + + public function providerActiveUrlField() + { + return array( + array(false, 'userName', array('class'=>'test-class-attr'), + '<input class="test-class-attr" name="CHtmlTestActiveModel[userName]" id="CHtmlTestActiveModel_userName" type="url" />'), + array(true, 'userName', array('another-attr'=>'another-attr-value', 'id'=>'changed-id'), + '<input another-attr="another-attr-value" id="changed-id" name="CHtmlTestActiveModel[userName]" type="url" class="error" />'), + array(false, 'firstName', array(), + '<input name="CHtmlTestActiveModel[firstName]" id="CHtmlTestActiveModel_firstName" type="url" />'), + array(true, 'firstName', array('disabled'=>true, 'name'=>'changed-name'), + '<input disabled="disabled" name="changed-name" id="changed-name" type="url" />'), + ); + } + + /** + * @dataProvider providerActiveUrlField + * + * @param boolean $validate + * @param string $attribute + * @param array $htmlOptions + * @param string $assertion + */ + public function testActiveUrlField($validate, $attribute, $htmlOptions, $assertion) + { + $model=new CHtmlTestActiveModel(); + if($validate) + $model->validate(); + $this->assertEquals($assertion, CHtml::activeUrlField($model, $attribute, $htmlOptions)); + } + + public function providerButton() + { + return array( + array('button1', array('name'=>null, 'class'=>'class1'), '<input class="class1" type="button" value="button1" />'), + array('button2', array('name'=>'custom-name', 'class'=>'class2'), '<input name="custom-name" class="class2" type="button" value="button2" />'), + array('button3', array('type'=>'submit'), '<input type="submit" name="yt0" value="button3" />'), + array('button4', array('value'=>'button-value'), '<input value="button-value" name="yt0" type="button" />'), + array('button5', array(), '<input name="yt0" type="button" value="button5" />'), + ); + } + + /** + * @dataProvider providerButton + * + * @param string $label + * @param array $htmlOptions + * @param string $assertion + */ + public function testButton($label, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::button($label, $htmlOptions)); + } + + public function providerHtmlButton() + { + return array( + array('button1', array('name'=>null, 'class'=>'class1'), '<button name="yt0" class="class1" type="button">button1</button>'), + array('button2', array('name'=>'custom-name', 'class'=>'class2'), '<button name="custom-name" class="class2" type="button">button2</button>'), + array('button3', array('type'=>'submit'), '<button type="submit" name="yt0">button3</button>'), + array('button4', array('value'=>'button-value'), '<button value="button-value" name="yt0" type="button">button4</button>'), + array('button5', array(), '<button name="yt0" type="button">button5</button>'), + ); + } + + /** + * @dataProvider providerHtmlButton + * + * @param string $label + * @param array $htmlOptions + * @param string $assertion + */ + public function testHtmlButton($label, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::htmlButton($label, $htmlOptions)); + } + + public function providerSubmitButton() + { + return array( + array('submit', array(), '<input type="submit" name="yt0" value="submit" />'), + array('submit1', array('type'=>'button'), '<input type="submit" name="yt0" value="submit1" />'), + ); + } + + /** + * @dataProvider providerSubmitButton + * + * @param string $label + * @param array $htmlOptions + * @param string $assertion + */ + public function testSubmitButton($label, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::submitButton($label, $htmlOptions)); + } + + public function providerResetButton() + { + return array( + array('reset', array(), '<input type="reset" name="yt0" value="reset" />'), + array('reset1', array('type'=>'button'), '<input type="reset" name="yt0" value="reset1" />'), + ); + } + + /** + * @dataProvider providerResetButton + * + * @param string $label + * @param array $htmlOptions + * @param string $assertion + */ + public function testResetButton($label, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::resetButton($label, $htmlOptions)); + } + + public function providerImageButton() + { + return array( + array('/images/test-image.png', array('src'=>'ignored-src'), '<input src="/images/test-image.png" type="image" name="yt0" />'), + array('/images/test-image.jpg', array('type'=>'button'), '<input type="image" src="/images/test-image.jpg" name="yt0" />'), + array('/images/test-image.gif', array('value'=>'image'), '<input value="image" src="/images/test-image.gif" type="image" name="yt0" />'), + ); + } + + /** + * @dataProvider providerImageButton + * + * @param string $src + * @param array $htmlOptions + * @param string $assertion + */ + public function testImageButton($label, $htmlOptions, $assertion) + { + $this->assertEquals($assertion, CHtml::imageButton($label, $htmlOptions)); + } + + public function providerLinkButton() + { + return array( + array('submit', array(), '<a href="#" id="yt0">submit</a>', + "jQuery('body').on('click','#yt0',function(){jQuery.yii.submitForm(this,'',{});return false;});"), + array('link-button', array(), '<a href="#" id="yt0">link-button</a>', + "jQuery('body').on('click','#yt0',function(){jQuery.yii.submitForm(this,'',{});return false;});"), + array('link-button', array('href'=>'http://yiiframework.com/'), '<a href="#" id="yt0">link-button</a>', + "jQuery('body').on('click','#yt0',function(){jQuery.yii.submitForm(this,'http://yiiframework.com/',{});return false;});"), + ); + } + + /** + * @dataProvider providerLinkButton + * + * @param string $label + * @param array $htmlOptions + * @param string $assertion + * @param string $clientScriptOutput + */ + public function testLinkButton($label, $htmlOptions, $assertion, $clientScriptOutput) + { + $this->assertEquals($assertion, CHtml::linkButton($label, $htmlOptions)); + + $output=''; + Yii::app()->getClientScript()->renderBodyEnd($output); + $this->assertTrue(mb_strpos($output, $clientScriptOutput)!==false); + } + + public function testAjaxCallbacks() + { + $out=CHtml::ajax(array( + 'success'=>'js:function() { /* callback */ }', + )); + $this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", null, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out); + + $out=CHtml::ajax(array( + 'success'=>'function() { /* callback */ }', + )); + $this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", null, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out); + + $out=CHtml::ajax(array( + 'success'=>new CJavaScriptExpression('function() { /* callback */ }'), + )); + $this->assertTrue(mb_strpos($out,"'success':function() { /* callback */ }", null, Yii::app()->charset)!==false, "Unexpected JavaScript: ".$out); + } +} + +/* Helper classes */ + +class CHtmlTestModel extends CModel +{ + private static $_names=array(); + + /** + * @property mixed $attr1 + */ + public $attr1; + + /** + * @property mixed $attr2 + */ + public $attr2; + + /** + * @property mixed $attr3 + */ + public $attr3; + + /** + * @property mixed $attr4 + */ + public $attr4; + + public function __constructor(array $properties) + { + foreach($properties as $property=>$value) + { + if(!property_exists($this, $property)) + { + throw new Exception("$property is not a property of this class, and I'm not allowing you to add it!"); + } + $this->{$property} = $value; + } + } + + /** + * Returns the list of attribute names. + * @return array list of attribute names. Defaults to all public properties of the class. + */ + public function attributeNames() + { + $className=get_class($this); + if(!isset(self::$_names[$className])) + { + $class=new ReflectionClass(get_class($this)); + $names=array(); + foreach($class->getProperties() as $property) + { + $name=$property->getName(); + if($property->isPublic() && !$property->isStatic()) + $names[]=$name; + } + return self::$_names[$className]=$names; + } + else + return self::$_names[$className]; + } + +} + +class CHtmlTestFormModel extends CFormModel +{ + public $stringAttr; + public $arrayAttr; + + public function afterConstruct() + { + $this->stringAttr='stringAttrValue'; + $this->arrayAttr=array( + 'k1'=>'v1', + 'k2'=>'v2', + 'k3'=>array( + 'k4'=>'v4', + 'k5'=>'v5', + ), + 'k6'=>'v6', + ); + } +} + +class CHtmlTestActiveModel extends CFormModel +{ + public $userName; + public $firstName; + + public function rules() + { + return array( + array('userName', 'required'), + array('firstName', 'safe'), + ); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJSONTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJSONTest.php new file mode 100644 index 0000000..51fc337 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJSONTest.php @@ -0,0 +1,79 @@ +<?php +Yii::import('system.db.CDbConnection'); +Yii::import('system.db.ar.CActiveRecord'); + +require_once(dirname(__FILE__).'/../../db/data/models.php'); + +/** + * CJSON Test + */ +class CJSONTest extends CTestCase { + private $db; + + protected function setUp() + { + if(!extension_loaded('pdo') || !extension_loaded('pdo_sqlite')) + $this->markTestSkipped('PDO and SQLite extensions are required.'); + + $this->db=new CDbConnection('sqlite::memory:'); + $this->db->active=true; + $this->db->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/../../db/data/sqlite.sql')); + CActiveRecord::$db=$this->db; + } + + protected function tearDown() + { + $this->db->active=false; + } + + /** + * native json_encode can't do it + * @return void + */ + public function testEncodeSingleAR(){ + $post = Post::model()->findByPk(1); + $this->assertEquals( + '{"id":"1","title":"post 1","create_time":"100000","author_id":"1","content":"content 1"}', + CJSON::encode($post) + ); + } + + /** + * native json_encode can't do it + * @return void + */ + public function testEncodeMultipleARs(){ + $posts=Post::model()->findAllByPk(array(1, 2)); + $this->assertEquals( + '[{"id":"1","title":"post 1","create_time":"100000","author_id":"1","content":"content 1"},{"id":"2","title":"post 2","create_time":"100001","author_id":"2","content":"content 2"}]', + CJSON::encode($posts) + ); + } + + public function testEncodeSimple(){ + $this->assertEquals("true", CJSON::encode(true)); + $this->assertEquals("false", CJSON::encode(false)); + $this->assertEquals("null", CJSON::encode(null)); + $this->assertEquals("123", CJSON::encode(123)); + $this->assertEquals("123.12", CJSON::encode(123.12)); + $this->assertEquals('"test\\\\me"', CJSON::encode('test\me')); + } + + public function testEncodeArray(){ + $objArr = array('a' => 'b'); + $arrArr = array('a', 'b'); + $mixedArr = array('c', 'a' => 'b'); + $nestedArr = array('a', 'b' => array('a', 'b' => 'c')); + + $this->assertEquals('{"a":"b"}', CJSON::encode($objArr)); + $this->assertEquals('["a","b"]', CJSON::encode($arrArr)); + $this->assertEquals('{"0":"c","a":"b"}', CJSON::encode($mixedArr)); + $this->assertEquals('{"0":"a","b":{"0":"a","b":"c"}}', CJSON::encode($nestedArr)); + } + + public function testDecode(){ + $this->assertEquals(array('c', 'a' => 'b'), CJSON::decode('{"0":"c","a":"b"}')); + $this->assertEquals(array('a', 'b'), CJSON::decode('["a","b"]')); + $this->assertEquals(array('a', 'b' => array('a', 'b' => 'c')), CJSON::decode('{"0":"a","b":{"0":"a","b":"c"}}')); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJavaScriptExpressionTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJavaScriptExpressionTest.php new file mode 100644 index 0000000..2e4c47a --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJavaScriptExpressionTest.php @@ -0,0 +1,12 @@ +<?php +/** + * CJavaScriptExpressionTest + */ +class CJavaScriptExpressionTest extends CTestCase +{ + public function testToString() + { + $expression=new CJavaScriptExpression("function(){return \"Hello, world!\";}"); + $this->assertEquals('function(){return "Hello, world!";}', $expression); + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJavaScriptTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJavaScriptTest.php new file mode 100644 index 0000000..a16a547 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/helpers/CJavaScriptTest.php @@ -0,0 +1,24 @@ +<?php +/** + * CJavaScriptTest + */ +class CJavaScriptTest extends CTestCase +{ + public function testLegacyEncode() + { + $expression=CJavaScript::encode("js:function() { /* callback */ }"); + $this->assertEquals("function() { /* callback */ }",$expression); + } + + public function testLegacyEncodeSafe() + { + $expression=CJavaScript::encode("js:function() { /* callback */ }",true); + $this->assertEquals("'js:function() { /* callback */ }'",$expression); + } + + public function testEncode() + { + $expression=CJavaScript::encode(new CJavaScriptExpression("function() { /* callback */ }")); + $this->assertEquals("function() { /* callback */ }",$expression); + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/CWsdlGeneratorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/CWsdlGeneratorTest.php new file mode 100644 index 0000000..1adf806 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/CWsdlGeneratorTest.php @@ -0,0 +1,156 @@ +<?php + +// path to tested class +Yii::import('system.web.services.CWsdlGenerator'); + +// paths to input-output objects +Yii::import('application.framework.web.services.*'); + +// path to soap (fake) controller +Yii::import('application.framework.web.controllers.*'); + +/** +* Unit test for Soap WSDL generator +*/ +class CWsdlGeneratorTest extends CTestCase{ + + /** + * Path where we will try to save generated WSDL + */ + protected $path; + + public function setUp(){ + if(!extension_loaded('dom')) + $this->markTestSkipped('DOM extension is required.'); + } + + /** + * Test generation of WSDL xml file + */ + public function testGenerateWsdl(){ + + $generator=new CWsdlGenerator(); + + // we use any URL location since unit test is executed via CLI and not real HTTP request + $wsdl=$generator->generateWsdl('SoapController','http://10.20.30.40/index.php?r=soap/calculator&ws=1'); + + // try to save XML output for manual checkup + // uncomment to save WSDL into file and test also a PHP soapClient + /* + $this->path=Yii::getPathOfAlias('application.runtime').DIRECTORY_SEPARATOR.'soap-wsdl-test.xml'; + if(is_file($this->path)) + unlink($this->path); + $this->assertTrue( 0 < file_put_contents($this->path, $wsdl), 'Failed saving WSDL into ['.$this->path.']'); + + // create SOAP client and check provided actions and types + $client=new SoapClient($this->path); + $functions=$client->__getFunctions(); + $this->assertTrue( count($functions) > 0 ); + $types=$client->__getTypes(); + $this->assertTrue( count($types) > 0 ); + */ + + $xml=simplexml_load_string($wsdl); + $this->assertTrue($xml instanceOf SimpleXMLElement); + + // check input attribute with all attributes (minOccurs, maxOccurs, nillable) + $node=$xml->xpath('//xsd:element[@name="subject"]'); + + $minOccurs=(string)$node[0]->attributes()->minOccurs; + $this->assertTrue($minOccurs==='1'); + + $maxOccurs=(string)$node[0]->attributes()->maxOccurs; + $this->assertTrue($maxOccurs==='1'); + + $nillable=(string)$node[0]->attributes()->nillable; + $this->assertTrue($nillable==='false'); + + $type=(string)$node[0]->attributes()->type; + $this->assertTrue($type==='xsd:integer'); + + // check input attribute with only nillable + $node=$xml->xpath('//xsd:element[@name="ins_start_date"]'); + + $minOccurs=(string)$node[0]->attributes()->minOccurs; + $this->assertTrue($minOccurs===''); // null converts to empty string + + $maxOccurs=(string)$node[0]->attributes()->maxOccurs; + $this->assertTrue($maxOccurs===''); + + $nillable=(string)$node[0]->attributes()->nillable; + $this->assertTrue($nillable==='true'); + + $type=(string)$node[0]->attributes()->type; + $this->assertTrue($type==='xsd:date'); + + // check some output attribute + $node=$xml->xpath('//xsd:element[@name="company_key"]'); + + $minOccurs=(string)$node[0]->attributes()->minOccurs; + $this->assertTrue($minOccurs==='1'); + + $maxOccurs=(string)$node[0]->attributes()->maxOccurs; + $this->assertTrue($maxOccurs==='1'); + + $nillable=(string)$node[0]->attributes()->nillable; + $this->assertTrue($nillable==='false'); + + $type=(string)$node[0]->attributes()->type; + $this->assertTrue($type==='xsd:string'); + + // check soap indicator-sequence + $nodes=$xml->xpath('//xsd:complexType[@name="SoapPovCalculationInput"]/xsd:sequence/*'); + $this->assertTrue(is_array($nodes) && count($nodes)>10); // there is 13 child nodes + + // check soap indicator-choice + $nodes=$xml->xpath('//xsd:complexType[@name="SoapInsurerPerson"]/xsd:choice/*'); + $this->assertTrue(is_array($nodes) && count($nodes)==2); // choose either physical or juristic person + + // check soap custom XML nodes injected into WSDL + //$node=$xml->xpath('//xsd:complexType[@name="SoapInsurerPersonPhysical"]/xsd:sequence/xsd:choice/xsd:element[name="age"]'); + $nodes=$xml->xpath('//xsd:complexType[@name="SoapInsurerPersonPhysical"]/xsd:sequence/xsd:choice/*'); + $type=(string)$nodes[1]->attributes()->type; + $this->assertTrue($type==='xsd:date'); + + // check maxOccurs=unbounded + $node=$xml->xpath('//xsd:complexType[@name="SoapInsurerPersonPhysical"]/xsd:sequence/xsd:element[@name="studentCardNumber"]'); + $maxOccurs=(string)$node[0]->attributes()->maxOccurs; + $this->assertTrue($maxOccurs==='unbounded'); + } + + /** + * Test generation of HTML documentation + */ + public function testGenerateHtmlDocumentation(){ + + $generator=new CWsdlGenerator(); + + // we dont care this time about WSDL, we simple must craete some parsed data + $generator->generateWsdl('SoapController','http://10.20.30.40/index.php?r=soap/calculator&ws=1'); + + // get HTML documentation + $html=$generator->buildHtmlDocs(true); + + // uncomment to save WSDL into file + /* + $this->path=Yii::getPathOfAlias('application.runtime').DIRECTORY_SEPARATOR.'soap-wsdl-test-doc.html'; + if(is_file($this->path)) + unlink($this->path); + $this->assertTrue( 0 < file_put_contents($this->path, $html), 'Failed saving WSDL into ['.$this->path.']'); + */ + + // check we have table for object SoapPovCalculationInput + $this->assertTrue(false!==strpos($html,'SoapPovCalculationInput')); + // check column Attribute in table SoapPovCalculationInput + $this->assertTrue(false!==strpos($html,'use_kind')); + // check column Type in table SoapPovCalculationInput + $this->assertTrue(false!==strpos($html,'integer')); + // check column Required in table SoapPovCalculationInput + $this->assertTrue(false!==strpos($html,'unbounded')); + // check column Description in table SoapPovCalculationInput + $this->assertTrue(false!==strpos($html,'the date of birth RRRR.MM.DD')); + // check column Example in table SoapPovCalculationInput + $this->assertTrue(false!==strpos($html,'85HN65')); + } + +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPerson.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPerson.php new file mode 100644 index 0000000..2615d0e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPerson.php @@ -0,0 +1,23 @@ +<?php +/** +* This is a container for SOAP complex object "insurer". +* It can be either a physical or a juristic person. +* The number of occurences is defined in attribute "insurer" of complex type "SoapPovCalculationInput" +* +* @soap-indicator choice +*/ +class SoapInsurerPerson { + + /** + * @var SoapInsurerPersonPhysical Physical persons. + * @soap + */ + public $insurerPersonPhysical; + + /** + * @var SoapInsurerPersonJuristic Juristic persons - companies. + * @soap + */ + public $insurerPersonJuristic; + +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPersonJuristic.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPersonJuristic.php new file mode 100644 index 0000000..153e986 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPersonJuristic.php @@ -0,0 +1,46 @@ +<?php +/** +* SOAP definitions for a juristic person. +* We always want to know the name of the company and its tax number. +* Optionally, full address can be also supplied. +* All attributes in any order. +*/ +class SoapInsurerPersonJuristic { + + /** + * @var string First name {minoccurs = 1, maxoccurs = 1, nillable = false} + * @soap + * @example TOP-Solutions Ltd. + */ + public $companyName; + + /** + * @var string Company tax number {minoccurs = 1, maxoccurs = 1, nillable = false} + * @example 112233445BB + * @soap + */ + public $companyTaxNumber; + + /** + * @var string Company street {minoccurs = 0, maxoccurs = 1, nillable = true} + * @example Wembley Hill Rd. + * @soap + */ + public $companyAddressStreet; + + /** + * @var string Company house number {minoccurs = 0, maxoccurs = 1, nillable = true} + * @example 45/c + * @soap + */ + public $companyAddressHouseNr; + + /** + * @var string Company ZIP postal code {minoccurs = 0, maxoccurs = 1, nillable = true} + * @example H7D 99B + * @soap + */ + public $companyAddressZip; + + +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPersonPhysical.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPersonPhysical.php new file mode 100644 index 0000000..b1de9a7 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapInsurerPersonPhysical.php @@ -0,0 +1,50 @@ +<?php +/** +* SOAP WSDL description of a physical person. +* In this example: +* - We want for each person to know either an age and date of birth. +* - We optionally want to know, whether a person is a student. +* +* Following custom piece of WSDL code will be inserted instead of automatically generated XML nodes. +* This will efficiently enable defining SOAP validations of any complexity. +* +* @soap-wsdl <xsd:sequence> +* @soap-wsdl <xsd:choice minOccurs="1" maxOccurs="1" nillable="false"> +* @soap-wsdl <xsd:element minOccurs="1" maxOccurs="1" nillable="false" name="age" type="xsd:integer"/> +* @soap-wsdl <xsd:element minOccurs="1" maxOccurs="1" nillable="false" name="date_of_birth" type="xsd:date"/> +* @soap-wsdl </xsd:choice> +* @soap-wsdl <xsd:element minOccurs="0" maxOccurs="1" nillable="false" name="student" type="xsd:boolean"/> +* @soap-wsdl <xsd:element minOccurs="0" maxOccurs="unbounded" nillable="false" name="studentCardNumber" type="xsd:boolean"/> +* @soap-wsdl </xsd:sequence> +*/ +class SoapInsurerPersonPhysical { + + /** + * @var integer Insurer age {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example 35 + * @soap + */ + public $age; + + /** + * @var date Date of birth {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example 1980-05-27 + * @soap + */ + public $date_of_birth; + + /** + * @var boolean Is insurer a student? (must have age between 17 - 16 years incl.) {nillable = 0, minOccurs = 0, maxOccurs = 1} + * @example true + * @soap + */ + public $student = false; + + /** + * @var string Serial number of any held student card. {minOccurs = 0, maxOccurs = unbounded} + * @example GO26-26110801B + * @soap + */ + public $studentCardNumber; + +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationInput.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationInput.php new file mode 100644 index 0000000..a2574cc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationInput.php @@ -0,0 +1,104 @@ +<?php +/** +* By default, WSDL generator assumes, that the order of object attributes in a complex type does not matter. +* In this object however, we want to have all attributes supplied in an expected order - thus we must set the soap indicator flag "sequence" for the WSDL generator. +* +* @soap-indicator sequence +*/ +class SoapPovCalculationInput +{ + /** + * @var integer Subject type (1 = physical person, 2 = juristic person) {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example: 1 + * @soap + */ + public $subject; + + /** + * @var integer Usage type <blockquote>1 - Private usage <br/>2 - Taxi<br/>3 - Rental cars</blockquote> {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example: 1 + * @soap + */ + public $use_kind; + + /** + * @var integer Engine volume 1 < ccm < 3500 ccm. + * @example: 1397 + * @soap + */ + public $ccm_personal; + + /** + * @var integer Engine power kW > 0 {nillable = 1} + * @example: 55 + * @soap + */ + public $car_power; + + /** + * @var integer Vehicle weight 0 < kg < 3500. {minOccurs = 1, maxOccurs = 1} + * @example: 1615 + * @soap + */ + public $car_kg; + + /** + * @var integer Year made. {nillable = false, minOccurs = 1, maxOccurs = 1} + * @example: 2001 + * @soap + */ + public $production_year; + + /** + * @var date Vehicle owner - the date of birth RRRR.MM.DD. {nillable = 0, minOccurs = 0, maxOccurs = 1} + * @example: 1980-12-31 + * @soap + */ + public $dob = null; + + /** + * @var date Insurance start date RRRR.MM.DD {nillable = true} + * @example: 2013-01-01 + * @soap + */ + public $ins_start_date; + + /** + * @var string ZIP code of insurer {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example 85HN65 + * @soap + */ + public $zip; + + /** + * @var integer Number of previous accidents 0 - 99. {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example: 1 + * @soap + */ + public $crash; + + /** + * @var integer Payment frequency, 1=annually, 2=half year, 4=quarterly. {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example: 2 + * @soap + */ + public $payment; + + /** + * @var integer Risk coverage type, 1=lower, 2=higher {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example: 1 + * @soap + */ + public $insurance_type; + + /** + * This variable tests various flexibility requirements on WSDL definitions, such as soap indicators (choice, sequence) and inserting any custom defined XML nodes into WSDL file. + * We want an insurer to be either a juristic or a physical person. There must be always at least 1 person and maximum 10 persons supplied. + * A juristic person is defined in class "SoapInsurerPersonJuristic" and physical person in class "SoapInsurerPersonPhysical". + * + * @var SoapInsurerPerson List of insured persons. It can be either a physical person or a juristic person {nillable = 0, minOccurs = 1, maxOccurs = 10} + * @soap + */ + public $insurer; + +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationOutput.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationOutput.php new file mode 100644 index 0000000..8966438 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationOutput.php @@ -0,0 +1,22 @@ +<?php +/** +* Datatype for calculation output. +*/ +class SoapPovCalculationOutput { + + /** + * @var integer calculation ID + * @example 187 + * @soap + */ + public $calculation_id; + + /** + * @var SoapPovCalculationResult[] Calculation result dataset + * @soap + */ + public $results; + + + +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationResult.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationResult.php new file mode 100644 index 0000000..35c7dcc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/services/SoapPovCalculationResult.php @@ -0,0 +1,49 @@ +<?php +/** +* Data structure returned from SOAP call calculate +*/ +class SoapPovCalculationResult { + + /** + * @var string Insurance company key {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example allianz + * @soap + */ + public $company_key; + + /** + * @var string Product name {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example AllRisk + * @soap + */ + public $product_name; + + /** + * @var string Insurance company full name {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example Allianz Ltd. + * @soap + */ + public $company_fullname; + + /** + * @var float Coverage for health mil. EUR {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example 1.5 + * @soap + */ + public $coverage_health; + + /** + * @var float Coverage for property in mil. EUR {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example 1.2 + * @soap + */ + public $coverage_property; + + /** + * @var integer Insurance premium EUR {nillable = 0, minOccurs = 1, maxOccurs = 1} + * @example 145 + * @soap + */ + public $premium; + +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CAutoCompleteTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CAutoCompleteTest.php new file mode 100644 index 0000000..93c230f --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CAutoCompleteTest.php @@ -0,0 +1,35 @@ +<?php +/** + * CAutoCompleteTest + */ +class CAutoCompleteTest extends CTestCase +{ + public function testCallbackEncoding() + { + $expected = "'highlight':function() { /* callback */ }"; + + $out=$this->getWidgetScript('js:function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out); + + $out=$this->getWidgetScript('function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out); + + $out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }')); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out); + } + + private function getWidgetScript($callback) + { + Yii::app()->clientScript->scripts = array(); + ob_start(); + $widget = new CAutoComplete(null); + $widget->name = 'test'; + $widget->highlight = $callback; + $widget->data = array(1, 2, 3); + $widget->init(); + $widget->run(); + Yii::app()->clientScript->render($out); + ob_end_clean(); + return $out; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CMaskedTextFieldTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CMaskedTextFieldTest.php new file mode 100644 index 0000000..d12bed0 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CMaskedTextFieldTest.php @@ -0,0 +1,35 @@ +<?php +/** + * CMaskedTextFieldTest + */ +class CMaskedTextFieldTest extends CTestCase +{ + public function testCallbackEncoding() + { + $expected = "'completed':function() { /* callback */ }"; + + $out=$this->getWidgetScript('js:function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out); + + $out=$this->getWidgetScript('function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out); + + $out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }')); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out); + } + + private function getWidgetScript($callback) + { + Yii::app()->clientScript->scripts = array(); + ob_start(); + $widget = new CMaskedTextField(null); + $widget->name = 'test'; + $widget->completed = $callback; + $widget->mask = '99/99/9999'; + $widget->init(); + $widget->run(); + Yii::app()->clientScript->render($out); + ob_end_clean(); + return $out; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CMultiFileUploadTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CMultiFileUploadTest.php new file mode 100644 index 0000000..2bbccaf --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CMultiFileUploadTest.php @@ -0,0 +1,34 @@ +<?php +/** + * CMultiFileUploadTest + */ +class CMultiFileUploadTest extends CTestCase +{ + public function testCallbackEncoding() + { + $expected = "'onFileSelect':function() { /* callback */ }"; + + $out=$this->getWidgetScript('js:function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out); + + $out=$this->getWidgetScript('function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out); + + $out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }')); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out); + } + + private function getWidgetScript($callback) + { + Yii::app()->clientScript->scripts = array(); + ob_start(); + $widget = new CMultiFileUpload(null); + $widget->name = 'test'; + $widget->options['onFileSelect'] = $callback; + $widget->init(); + $widget->run(); + Yii::app()->clientScript->render($out); + ob_end_clean(); + return $out; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CStarRatingTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CStarRatingTest.php new file mode 100644 index 0000000..870aaf2 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/web/widgets/CStarRatingTest.php @@ -0,0 +1,34 @@ +<?php +/** + * CStarRatingTest + */ +class CStarRatingTest extends CTestCase +{ + public function testCallbackEncoding() + { + $expected = "'callback':function() { /* callback */ }"; + + $out=$this->getWidgetScript('js:function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out); + + $out=$this->getWidgetScript('function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out); + + $out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }')); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out); + } + + private function getWidgetScript($callback) + { + Yii::app()->clientScript->scripts = array(); + ob_start(); + $widget = new CStarRating(null); + $widget->name = 'test'; + $widget->callback = $callback; + $widget->init(); + $widget->run(); + Yii::app()->clientScript->render($out); + ob_end_clean(); + return $out; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/behaviors/CTimestampBehaviorTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/behaviors/CTimestampBehaviorTest.php new file mode 100644 index 0000000..c51ff35 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/behaviors/CTimestampBehaviorTest.php @@ -0,0 +1,163 @@ +<?php + +class CTimestampBehaviorTest extends CTestCase +{ + private $_connection; + + protected function setUp() + { + // pdo and pdo_sqlite extensions are obligatory + if(!extension_loaded('pdo') || !extension_loaded('pdo_sqlite')) + $this->markTestSkipped('PDO and SQLite extensions are required.'); + + // open connection and create testing tables + $this->_connection=new CDbConnection('sqlite::memory:'); + $this->_connection->active=true; + $this->_connection->pdoInstance->exec(file_get_contents(dirname(__FILE__).'/CTimestampBehaviorTest.sql')); + CActiveRecord::$db=$this->_connection; + } + + protected function tearDown() + { + // close connection + $this->_connection->active=false; + } + + public function testCreateAttribute() + { + // behavior changes created_at after inserting + $model1=new CTimestampBehaviorTestActiveRecord; + $model1->attachBehavior('timestampBehavior', array( + 'class'=>'zii.behaviors.CTimestampBehavior', + 'createAttribute'=>'created_at', + 'updateAttribute'=>null, + 'setUpdateOnCreate'=>false, + )); + $model1->title='testing-row-1'; + $this->assertEquals(0, $model1->created_at); + $saveTime=time(); + $model1->save(); + $this->assertEquals($saveTime, $model1->created_at, '', 2); + + // behavior changes created_at after inserting + $model2=new CTimestampBehaviorTestActiveRecord; + $model2->attachBehavior('timestampBehavior', array( + 'class'=>'zii.behaviors.CTimestampBehavior', + 'createAttribute'=>'created_at', + 'updateAttribute'=>null, + 'setUpdateOnCreate'=>false, + )); + $model2->title='testing-row-2'; + $model2->created_at=123123; + $this->assertEquals(123123, $model2->created_at); + $saveTime=time(); + $model2->save(); + $this->assertEquals($saveTime, $model2->created_at, '', 2); + + // behavior does not changes created_at after inserting + $model3=new CTimestampBehaviorTestActiveRecord; + $model3->attachBehavior('timestampBehavior', array( + 'class'=>'zii.behaviors.CTimestampBehavior', + 'createAttribute'=>null, + 'updateAttribute'=>null, + 'setUpdateOnCreate'=>false, + )); + $model3->title='testing-row-3'; + $model3->created_at=321321; + $this->assertEquals(321321, $model3->created_at); + $model3->save(); + $this->assertEquals(321321, $model3->created_at); + } + + public function testUpdateAttribute() + { + // behavior changes updated_at after updating + $model1=CTimestampBehaviorTestActiveRecord::model()->findByPk(1); + $model1->attachBehavior('timestampBehavior', array( + 'class'=>'zii.behaviors.CTimestampBehavior', + 'createAttribute'=>null, + 'updateAttribute'=>'updated_at', + 'setUpdateOnCreate'=>false, + )); + $this->assertEquals(1340529410, $model1->updated_at); + $saveTime=time(); + $model1->save(); + $this->assertEquals($saveTime, $model1->updated_at, '', 2); + + // behavior changes updated_at after updating + $model2=CTimestampBehaviorTestActiveRecord::model()->findByPk(2); + $model2->attachBehavior('timestampBehavior', array( + 'class'=>'zii.behaviors.CTimestampBehavior', + 'createAttribute'=>null, + 'updateAttribute'=>'updated_at', + 'setUpdateOnCreate'=>true, + )); + $this->assertEquals(1340529305, $model2->updated_at); + $saveTime=time(); + $model2->save(); + $this->assertEquals($saveTime, $model2->updated_at, '', 2); + + // behavior does not changes updated_at after updating + $model3=CTimestampBehaviorTestActiveRecord::model()->findByPk(3); + $model3->attachBehavior('timestampBehavior', array( + 'class'=>'zii.behaviors.CTimestampBehavior', + 'createAttribute'=>null, + 'updateAttribute'=>null, + 'setUpdateOnCreate'=>false, + )); + $this->assertEquals(1340529200, $model3->updated_at); + $model3->save(); + $this->assertEquals(1340529200, $model3->updated_at); + + // behavior does not changes updated_at after inserting + $model4=new CTimestampBehaviorTestActiveRecord; + $model4->attachBehavior('timestampBehavior', array( + 'class'=>'zii.behaviors.CTimestampBehavior', + 'createAttribute'=>null, + 'updateAttribute'=>'updated_at', + 'setUpdateOnCreate'=>false, + )); + $model4->title='testing-row-3'; + $model4->updated_at=321321321; + $this->assertEquals(321321321, $model4->updated_at); + $model4->save(); + $this->assertEquals(321321321, $model4->updated_at); + + // behavior changes updated_at after inserting + $model5=new CTimestampBehaviorTestActiveRecord; + $model5->attachBehavior('timestampBehavior', array( + 'class'=>'zii.behaviors.CTimestampBehavior', + 'createAttribute'=>null, + 'updateAttribute'=>'updated_at', + 'setUpdateOnCreate'=>true, + )); + $model5->title='testing-row-3'; + $model5->updated_at=123123123; + $this->assertEquals(123123123, $model5->updated_at); + $saveTime=time(); + $model5->save(); + $this->assertEquals($saveTime, $model5->updated_at, '', 2); + } +} + +/** + * @property integer $id + * @property string $title + * @property integer $created_at + * @property integer $updated_at + */ +class CTimestampBehaviorTestActiveRecord extends CActiveRecord +{ + /** + * @return CTimestampBehaviorTestActiveRecord + */ + public static function model($className=__CLASS__) + { + return parent::model($className); + } + + public function tableName() + { + return 'table'; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/behaviors/CTimestampBehaviorTest.sql b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/behaviors/CTimestampBehaviorTest.sql new file mode 100644 index 0000000..1e66dda --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/behaviors/CTimestampBehaviorTest.sql @@ -0,0 +1,11 @@ +CREATE TABLE "table" +( + "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + "title" TEXT NOT NULL, + "created_at" INTEGER NOT NULL DEFAULT 0, + "updated_at" INTEGER NOT NULL DEFAULT 0 +); + +INSERT INTO "main"."table" VALUES (1, 'row1', 1340529410, 1340529410); +INSERT INTO "main"."table" VALUES (2, 'row2', 1340529305, 1340529305); +INSERT INTO "main"."table" VALUES (3, 'row3', 1340529200, 1340529200); diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/CGridViewTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/CGridViewTest.php new file mode 100644 index 0000000..bff8b6a --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/CGridViewTest.php @@ -0,0 +1,53 @@ +<?php +/** + * CGridViewTest + */ +class CGridViewTest extends CTestCase +{ + public function testCallbackEncoding() + { + $expected = "'beforeAjaxUpdate':function() { /* callback1 */ },'afterAjaxUpdate':function() { /* callback2 */ },'ajaxUpdateError':function() { /* callback3 */ },'selectionChanged':function() { /* callback4 */ }"; + + $out=$this->getWidgetScript( + 'js:function() { /* callback1 */ }', + 'js:function() { /* callback2 */ }', + 'js:function() { /* callback3 */ }', + 'js:function() { /* callback4 */ }' + ); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out); + + $out=$this->getWidgetScript( + 'function() { /* callback1 */ }', + 'function() { /* callback2 */ }', + 'function() { /* callback3 */ }', + 'function() { /* callback4 */ }' + ); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out); + + $out=$this->getWidgetScript( + new CJavaScriptExpression('function() { /* callback1 */ }'), + new CJavaScriptExpression('function() { /* callback2 */ }'), + new CJavaScriptExpression('function() { /* callback3 */ }'), + new CJavaScriptExpression('function() { /* callback4 */ }') + ); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out); + } + + private function getWidgetScript($callback1, $callback2, $callback3, $callback4) + { + Yii::import('zii.widgets.grid.CGridView'); + Yii::app()->clientScript->scripts = array(); + ob_start(); + $widget = new CGridView(null); + $widget->beforeAjaxUpdate = $callback1; + $widget->afterAjaxUpdate = $callback2; + $widget->ajaxUpdateError = $callback3; + $widget->selectionChanged = $callback4; + $widget->dataProvider = new CArrayDataProvider(array(1, 2, 3)); + $widget->init(); + $widget->registerClientScript(); + Yii::app()->clientScript->render($out); + ob_end_clean(); + return $out; + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/CListViewTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/CListViewTest.php new file mode 100644 index 0000000..eec6b18 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/CListViewTest.php @@ -0,0 +1,37 @@ +<?php +/** + * CListViewTest + */ +class CListViewTest extends CTestCase +{ + public function testCallbackEncoding() + { + $expected = "'beforeAjaxUpdate':function() { /* callback1 */ },'afterAjaxUpdate':function() { /* callback2 */ }"; + + $out=$this->getWidgetScript('js:function() { /* callback1 */ }', 'js:function() { /* callback2 */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out); + + $out=$this->getWidgetScript('function() { /* callback1 */ }', 'function() { /* callback2 */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out); + + $out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback1 */ }'), new CJavaScriptExpression('function() { /* callback2 */ }')); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out); + } + + private function getWidgetScript($callback1, $callback2) + { + Yii::import('zii.widgets.CListView'); + Yii::app()->clientScript->scripts = array(); + ob_start(); + $widget = new CListView(null); + $widget->beforeAjaxUpdate = $callback1; + $widget->afterAjaxUpdate = $callback2; + $widget->itemView = 'dummy'; + $widget->dataProvider = new CArrayDataProvider(array(1, 2, 3)); + $widget->init(); + $widget->registerClientScript(); + Yii::app()->clientScript->render($out); + ob_end_clean(); + return $out; + } +} \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/grid/CButtonColumnTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/grid/CButtonColumnTest.php new file mode 100644 index 0000000..1db98ac --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/grid/CButtonColumnTest.php @@ -0,0 +1,39 @@ +<?php +/** + * CButtonColumnTest + */ +class CButtonColumnTest extends CTestCase +{ + public function testCallbackEncoding() + { + $expected = "jQuery(document).on('click','#grid1 a.view',function() { /* callback */ });"; + + $out=$this->getWidgetScript('js:function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out); + + $out=$this->getWidgetScript('function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out); + + $out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }')); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out); + } + + private function getWidgetScript($callback) + { + Yii::import('zii.widgets.grid.CButtonColumn'); + Yii::app()->clientScript->scripts = array(); + ob_start(); + $grid = new stdClass(); + $grid->id = 'grid1'; + $widget = $this->getMock('CButtonColumn', array('initDefaultButtons'), array($grid)); + $widget->buttons = array( + 'view' => array( + 'click'=>$callback, + ), + ); + $widget->init(); + Yii::app()->clientScript->render($out); + ob_end_clean(); + return $out; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/jui/CJuiButtonTest.php b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/jui/CJuiButtonTest.php new file mode 100644 index 0000000..f61b661 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/framework/zii/widgets/jui/CJuiButtonTest.php @@ -0,0 +1,35 @@ +<?php +/** + * CJuiButtonTest + */ +class CJuiButtonTest extends CTestCase +{ + public function testCallbackEncoding() + { + $expected = ".click(function() { /* callback */ });"; + + $out=$this->getWidgetScript('js:function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (js:): ".$out); + + $out=$this->getWidgetScript('function() { /* callback */ }'); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (w/o js:): ".$out); + + $out=$this->getWidgetScript(new CJavaScriptExpression('function() { /* callback */ }')); + $this->assertTrue(mb_strpos($out,$expected, null, Yii::app()->charset)!==false, "Unexpected JavaScript (wrap): ".$out); + } + + private function getWidgetScript($callback) + { + Yii::import('zii.widgets.jui.CJuiButton'); + Yii::app()->clientScript->scripts = array(); + ob_start(); + $widget = new CJuiButton(null); + $widget->name = 'test'; + $widget->onclick = $callback; + $widget->init(); + $widget->run(); + Yii::app()->clientScript->render($out); + ob_end_clean(); + return $out; + } +} diff --git a/src/common/lib/vendor/yiisoft/yii/tests/phpunit.xml b/src/common/lib/vendor/yiisoft/yii/tests/phpunit.xml new file mode 100644 index 0000000..a6b5948 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/phpunit.xml @@ -0,0 +1,7 @@ +<phpunit bootstrap="bootstrap.php" + colors="false" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + stopOnFailure="false"> +</phpunit> \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/readme.txt b/src/common/lib/vendor/yiisoft/yii/tests/readme.txt new file mode 100644 index 0000000..3d5b8fe --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/readme.txt @@ -0,0 +1,13 @@ +This folder contains unit tests of Yii framework. +PHPUnit 3.5+ and xdebug (for code coverage report) are required. + +To run a single unit test, use: +>> phpunit path/to/test.php + +To run all tests under a directory, use: +>> phpunit --verbose path/to/tests/directory + +To generate code coverage report: +>> phpunit --coverage-html reports path/to/tests/directory/or/test/class + +Please use 'phpunit --help' to see more command line options. \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/reports/.gitignore b/src/common/lib/vendor/yiisoft/yii/tests/reports/.gitignore new file mode 100644 index 0000000..5e4debc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/reports/.gitignore @@ -0,0 +1 @@ +* diff --git a/src/common/lib/vendor/yiisoft/yii/tests/runtime/.gitignore b/src/common/lib/vendor/yiisoft/yii/tests/runtime/.gitignore new file mode 100644 index 0000000..5e4debc --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/runtime/.gitignore @@ -0,0 +1 @@ +* diff --git a/src/common/lib/vendor/yiisoft/yii/tests/rununit.bat b/src/common/lib/vendor/yiisoft/yii/tests/rununit.bat new file mode 100644 index 0000000..859e511 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/rununit.bat @@ -0,0 +1 @@ +phpunit --verbose framework \ No newline at end of file diff --git a/src/common/lib/vendor/yiisoft/yii/tests/travis/README.md b/src/common/lib/vendor/yiisoft/yii/tests/travis/README.md new file mode 100644 index 0000000..8bf2b7b --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/travis/README.md @@ -0,0 +1,12 @@ +This directory contains scripts for automated test runs via the [Travis CI](http://travis-ci.org) build service. They are used for the preparation of worker instances by setting up needed extensions and configuring database access. + +These scripts might be used to configure your own system for test runs. But since their primary purpose remains to support Travis in running the test cases, you would be best advised to stick to the setup notes in the tests themselves. + +The scripts are: + + - [`memcache-setup.sh`](memcache-setup.sh) + Compiles and installs the [memcache pecl extension](http://pecl.php.net/package/memcache) + - [`mysql-setup.sh`](mysql-setup.sh) + Prepares the [MySQL](http://www.mysql.com) server instance by creating the test database and granting access to it + - [`postgresql-setup.sh`](postgresql-setup.sh) + Same for [PostgreSQL](http://www.postgresql.org/) diff --git a/src/common/lib/vendor/yiisoft/yii/tests/travis/memcache-setup.sh b/src/common/lib/vendor/yiisoft/yii/tests/travis/memcache-setup.sh new file mode 100644 index 0000000..32629f0 --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/travis/memcache-setup.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +install_memcache() { + if [ "$(expr "$TRAVIS_PHP_VERSION" ">=" "5.5")" -eq 1 ]; then + MEMCACHE_VERSION="2.2.7" + wget "http://pecl.php.net/get/memcache-$MEMCACHE_VERSION.tgz" && + tar -zxf "memcache-$MEMCACHE_VERSION.tgz" && + sh -c "cd memcache-$MEMCACHE_VERSION && phpize && ./configure --enable-memcache && make && sudo make install" + fi + + echo "extension=memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + + return $? +} + +install_memcache > ~/memcache.log || ( echo "=== MEMCACHE BUILD FAILED ==="; cat ~/memcache.log ) diff --git a/src/common/lib/vendor/yiisoft/yii/tests/travis/mysql-setup.sh b/src/common/lib/vendor/yiisoft/yii/tests/travis/mysql-setup.sh new file mode 100644 index 0000000..936bc6e --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/travis/mysql-setup.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +mysql -u root -e 'CREATE SCHEMA `yii` CHARACTER SET utf8 COLLATE utf8_general_ci; GRANT ALL ON `yii`.* TO test@localhost IDENTIFIED BY "test"; FLUSH PRIVILEGES;' diff --git a/src/common/lib/vendor/yiisoft/yii/tests/travis/postgresql-setup.sh b/src/common/lib/vendor/yiisoft/yii/tests/travis/postgresql-setup.sh new file mode 100644 index 0000000..da4d8eb --- /dev/null +++ b/src/common/lib/vendor/yiisoft/yii/tests/travis/postgresql-setup.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +psql -q -c "CREATE ROLE test WITH PASSWORD 'test' LOGIN;" -U postgres +psql -q -c 'CREATE DATABASE yii WITH OWNER = test;' -U postgres +psql -q -c 'GRANT ALL PRIVILEGES ON DATABASE yii TO test;' -U postgres diff --git a/src/common/messages/.gitkeep b/src/common/messages/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/common/models/.gitkeep b/src/common/models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/common/schema/.gitkeep b/src/common/schema/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/common/widgets/.gitkeep b/src/common/widgets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/composer.json b/src/composer.json new file mode 100644 index 0000000..eac7af8 --- /dev/null +++ b/src/composer.json @@ -0,0 +1,53 @@ +{ + "name": "yiinitializr/intermediate", + "description": "Intermediate project structure for Yii PHP framework.", + "keywords": ["yii", "application", "web", "boilerplate", "template"], + "homepage": "http://2amigos.us", + "type": "yii-application", + "license": "BSD-3-Clause", + "description": "description_text", + "minimum-stability": "stable", + "config": { + "vendor-dir": "common/lib/vendor" + }, + "authors": [ + { + "name": "Antonio Ramirez Cobos", + "email": "amigo.cobos@gmail.com", + "homepage": "http://www.ramirezcobos.com" + }, + { + "name": "Matt Tabin", + "email": "amigo.tabin@gmail.com", + "homepage": "http://2amigos.us" + } + ], + "repositories": [ + { + "type": "composer", + "url": "http://packages.phundament.com" + } + ], + "require": { + "yiisoft/yii": "dev-master", + "2amigos/yiistrap": "dev-master", + "2amigos/yiiwheels": "dev-master" + }, + "autoload": { + "psr-0": { + "Yiinitializr": "common/lib/" + } + }, + "scripts": { + "pre-install-cmd": "Yiinitializr\\Composer\\Callback::preInstall", + "post-install-cmd": "Yiinitializr\\Composer\\Callback::postInstall", + "pre-update-cmd": "Yiinitializr\\Composer\\Callback::preUpdate", + "post-update-cmd": "Yiinitializr\\Composer\\Callback::postUpdate", + "post-package-install": [ + "Yiinitializr\\Composer\\Callback::postPackageInstall" + ], + "post-package-update": [ + "Yiinitializr\\Composer\\Callback::postPackageUpdate" + ] + } +} diff --git a/src/composer.lock b/src/composer.lock new file mode 100644 index 0000000..df55ee0 --- /dev/null +++ b/src/composer.lock @@ -0,0 +1,122 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" + ], + "hash": "9fb6fab9495c1c5b6ecc0847ad0304e0", + "packages": [ + { + "name": "2amigos/yiistrap", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/2amigos/yiistrap.git", + "reference": "c87f8050f8d4b181c440f78eb5e0cf795e5fa9b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/2amigos/yiistrap/zipball/c87f8050f8d4b181c440f78eb5e0cf795e5fa9b3", + "reference": "c87f8050f8d4b181c440f78eb5e0cf795e5fa9b3", + "shasum": "" + }, + "type": "yii-extension", + "notification-url": "http://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Christoffer Niska", + "email": "christoffer.niska@gmail.com", + "homepage": "http://www.cniska.net/" + }, + { + "name": "Antonio Ramirez", + "email": "ramirez.cobos@gmail.com", + "homepage": "http://www.ramirezcobos.com/" + } + ], + "description": "Twitter Bootstrap for the Yii PHP framework. Own maintained version.", + "keywords": [ + "bootstrap", + "yii" + ], + "time": "2013-05-14 17:49:15" + }, + { + "name": "2amigos/yiiwheels", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/2amigos/yiiwheels.git", + "reference": "d03bec6e021580c54748c81fab4ea38178bfc1d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/2amigos/yiiwheels/zipball/d03bec6e021580c54748c81fab4ea38178bfc1d4", + "reference": "d03bec6e021580c54748c81fab4ea38178bfc1d4", + "shasum": "" + }, + "require": { + "2amigos/yiistrap": "dev-master" + }, + "type": "yii-extension", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Antonio Ramirez", + "email": "ramirez.cobos@gmail.com", + "homepage": "http://www.ramirezcobos.com/" + } + ], + "description": "Extension library for Yiistrap, Yii Twitter's Bootstrap.", + "keywords": [ + "bootstrap" + ], + "support": { + "source": "https://github.com/2amigos/yiiwheels/tree/master", + "issues": "https://github.com/2amigos/yiiwheels/issues" + }, + "time": "2013-06-03 17:29:18" + }, + { + "name": "yiisoft/yii", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii.git", + "reference": "053a6a6a578625733d78c8c38380f19d1542e99c" + }, + "dist": { + "type": "zip", + "url": "https://github.com/yiisoft/yii/archive/053a6a6a578625733d78c8c38380f19d1542e99c.zip", + "reference": null, + "shasum": null + }, + "type": "library", + "description": "Yii PHP Framework", + "homepage": "https://github.com/yiisoft/yii", + "time": "2013-06-12 18:39:55" + } + ], + "packages-dev": [ + + ], + "aliases": [ + + ], + "minimum-stability": "stable", + "stability-flags": { + "yiisoft/yii": 20, + "2amigos/yiistrap": 20, + "2amigos/yiiwheels": 20 + }, + "platform": [ + + ], + "platform-dev": [ + + ] +} diff --git a/src/composer.phar b/src/composer.phar new file mode 100644 index 0000000000000000000000000000000000000000..9569572050dc6c673115c3809edd5248f83856d0 GIT binary patch literal 808348 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 DXj&9f literal 0 HcmV?d00001 diff --git a/src/console/commands/.gitkeep b/src/console/commands/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/console/components/.gitkeep b/src/console/components/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/console/config/console.php b/src/console/config/console.php new file mode 100644 index 0000000..9a8d277 --- /dev/null +++ b/src/console/config/console.php @@ -0,0 +1,22 @@ +<?php +/** + * + * console.php configuration file + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +defined('APP_CONFIG_NAME') or define('APP_CONFIG_NAME', 'console'); + +return array( + 'basePath' => realPath(__DIR__ . '/..'), + 'commandMap' => array( + 'migrate' => array( + 'class' => 'system.cli.commands.MigrateCommand', + 'migrationPath' => 'application.migrations' + ) + ) +); \ No newline at end of file diff --git a/src/console/config/env.php b/src/console/config/env.php new file mode 100644 index 0000000..95f89e9 --- /dev/null +++ b/src/console/config/env.php @@ -0,0 +1,35 @@ +<?php +/** + * + * dev.php configuration file + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'modules' => array( + 'gii' => array( + 'class' => 'system.gii.GiiModule', + 'password' => 'yii', + 'ipFilters' => array('127.0.0.1','::1'), + ), + ), + 'components' => array( + 'db' => array( + 'connectionString' => 'mysql:host=localhost;dbname=factuges_dev', + 'username' => 'root', + 'password' => '', + 'enableProfiling' => true, + 'enableParamLogging' => true, + 'charset' => 'utf8', + ), + ), + 'params' => array( + 'yii.handleErrors' => true, + 'yii.debug' => true, + 'yii.traceLevel' => 3, + ) +); \ No newline at end of file diff --git a/src/console/config/env/dev.php b/src/console/config/env/dev.php new file mode 100644 index 0000000..95f89e9 --- /dev/null +++ b/src/console/config/env/dev.php @@ -0,0 +1,35 @@ +<?php +/** + * + * dev.php configuration file + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'modules' => array( + 'gii' => array( + 'class' => 'system.gii.GiiModule', + 'password' => 'yii', + 'ipFilters' => array('127.0.0.1','::1'), + ), + ), + 'components' => array( + 'db' => array( + 'connectionString' => 'mysql:host=localhost;dbname=factuges_dev', + 'username' => 'root', + 'password' => '', + 'enableProfiling' => true, + 'enableParamLogging' => true, + 'charset' => 'utf8', + ), + ), + 'params' => array( + 'yii.handleErrors' => true, + 'yii.debug' => true, + 'yii.traceLevel' => 3, + ) +); \ No newline at end of file diff --git a/src/console/config/env/prod.php b/src/console/config/env/prod.php new file mode 100644 index 0000000..af21643 --- /dev/null +++ b/src/console/config/env/prod.php @@ -0,0 +1,29 @@ +<?php +/** + * + * prod.php configuration file + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'components' => array( +// 'db' => array( +// // setup to suit your needs +// 'connectionString' => '{DB_CONNECTION}', +// 'username' => '{DB_USER}', +// 'password' => '{DB_PASSWORD}', +// 'enableProfiling' => false, +// 'enableParamLogging' => false, +// 'charset' => 'utf8', +// ), + ), + 'params' => array( + 'yii.debug' => false, + 'yii.traceLevel' => 0, + 'yii.handleErrors' => APP_CONFIG_NAME !== 'test', + ) +); \ No newline at end of file diff --git a/src/console/data/.gitkeep b/src/console/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/console/extensions/.gitkeep b/src/console/extensions/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/console/migrations/.gitkeep b/src/console/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/console/models/.gitkeep b/src/console/models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/components/.gitkeep b/src/frontend/components/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/config/env.php b/src/frontend/config/env.php new file mode 100644 index 0000000..f742548 --- /dev/null +++ b/src/frontend/config/env.php @@ -0,0 +1,35 @@ +<?php +/** + * + * dev.php configuration file + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'modules' => array( + 'gii' => array( + 'class' => 'system.gii.GiiModule', + 'password' => 'yii', + 'ipFilters' => array('127.0.0.1','::1'), + ), + ), + 'components' => array( + 'db' => array( + 'connectionString' => 'mysql:host=localhost;dbname=factuges_dev', + 'username' => 'root', + 'password' => '', + 'enableProfiling' => true, + 'enableParamLogging' => true, + 'charset' => 'utf8', + ), + ), + 'params' => array( + 'yii.handleErrors' => true, + 'yii.debug' => true, + 'yii.traceLevel' => 3, + ) +); \ No newline at end of file diff --git a/src/frontend/config/env/dev.php b/src/frontend/config/env/dev.php new file mode 100644 index 0000000..f742548 --- /dev/null +++ b/src/frontend/config/env/dev.php @@ -0,0 +1,35 @@ +<?php +/** + * + * dev.php configuration file + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'modules' => array( + 'gii' => array( + 'class' => 'system.gii.GiiModule', + 'password' => 'yii', + 'ipFilters' => array('127.0.0.1','::1'), + ), + ), + 'components' => array( + 'db' => array( + 'connectionString' => 'mysql:host=localhost;dbname=factuges_dev', + 'username' => 'root', + 'password' => '', + 'enableProfiling' => true, + 'enableParamLogging' => true, + 'charset' => 'utf8', + ), + ), + 'params' => array( + 'yii.handleErrors' => true, + 'yii.debug' => true, + 'yii.traceLevel' => 3, + ) +); \ No newline at end of file diff --git a/src/frontend/config/env/prod.php b/src/frontend/config/env/prod.php new file mode 100644 index 0000000..5cca4c6 --- /dev/null +++ b/src/frontend/config/env/prod.php @@ -0,0 +1,29 @@ +<?php +/** + * + * prod.php configuration file + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +return array( + 'components' => array( +// 'db' => array( +// // setup to suit your needs +// 'connectionString' => '{DB_CONNECTION}', +// 'username' => '{DB_USER}', +// 'password' => '{DB_PASSWORD}', +// 'enableProfiling' => false, +// 'enableParamLogging' => false, +// 'charset' => 'utf8', +// ), + ), + 'params' => array( + 'yii.debug' => false, + 'yii.traceLevel' => 0, + 'yii.handleErrors' => APP_CONFIG_NAME !== 'test', + ) +); \ No newline at end of file diff --git a/src/frontend/config/frontend.php b/src/frontend/config/frontend.php new file mode 100644 index 0000000..e915741 --- /dev/null +++ b/src/frontend/config/frontend.php @@ -0,0 +1,66 @@ +<?php +/** + * + * frontend.php configuration file + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +defined('APP_CONFIG_NAME') or define('APP_CONFIG_NAME', 'frontend'); + +// web application configuration +return array( + 'name' => '{APPLICATION NAME}', + 'basePath' => realPath(__DIR__ . '/..'), + // path aliases + 'aliases' => array( + 'bootstrap' => dirname(__FILE__) . '/../..' . '/common/lib/vendor/2amigos/yiistrap', + 'yiiwheels' => dirname(__FILE__) . '/../..' . '/common/lib/vendor/2amigos/yiiwheels' + ), + + // application behaviors + 'behaviors' => array(), + + // controllers mappings + 'controllerMap' => array(), + + // application modules + 'modules' => array(), + + // application components + 'components' => array( + + 'bootstrap' => array( + 'class' => 'bootstrap.components.TbApi', + ), + + 'clientScript' => array( + 'scriptMap' => array( + 'bootstrap.min.css' => false, + 'bootstrap.min.js' => false, + 'bootstrap-yii.css' => false + ) + ), + 'urlManager' => array( + // uncomment the following if you have enabled Apache's Rewrite module. + 'urlFormat' => 'path', + 'showScriptName' => false, + + 'rules' => array( + // default rules + '<controller:\w+>/<id:\d+>' => '<controller>/view', + '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>', + '<controller:\w+>/<action:\w+>' => '<controller>/<action>', + ), + ), + 'user' => array( + 'allowAutoLogin' => true, + ), + 'errorHandler' => array( + 'errorAction' => 'site/error', + ) + ), +); \ No newline at end of file diff --git a/src/frontend/controllers/SiteController.php b/src/frontend/controllers/SiteController.php new file mode 100644 index 0000000..d61e88d --- /dev/null +++ b/src/frontend/controllers/SiteController.php @@ -0,0 +1,32 @@ +<?php +/** + * + * SiteController class + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +class SiteController extends EController +{ + public function actionIndex() + { + $this->render('index'); + } + + /** + * This is the action to handle external exceptions. + */ + public function actionError() + { + if($error=Yii::app()->errorHandler->error) + { + if(Yii::app()->request->isAjaxRequest) + echo $error['message']; + else + $this->render('error', $error); + } + } +} \ No newline at end of file diff --git a/src/frontend/extensions/.gitkeep b/src/frontend/extensions/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/helpers/.gitkeep b/src/frontend/helpers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/lib/.gitkeep b/src/frontend/lib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/models/.gitkeep b/src/frontend/models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/modules/.gitkeep b/src/frontend/modules/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/tests/.gitkeep b/src/frontend/tests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/views/layouts/main.php b/src/frontend/views/layouts/main.php new file mode 100644 index 0000000..1810214 --- /dev/null +++ b/src/frontend/views/layouts/main.php @@ -0,0 +1,106 @@ +<?php +/** + * + * main.php layout + * + * @author Antonio Ramirez <amigo.cobos@gmail.com> + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +?> +<!DOCTYPE html> +<!--[if lt IE 7]> +<html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> +<!--[if IE 7]> +<html class="no-js lt-ie9 lt-ie8"> <![endif]--> +<!--[if IE 8]> +<html class="no-js lt-ie9"> <![endif]--> +<!--[if gt IE 8]><!--> +<html class="no-js"> <!--<![endif]--> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <title> + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/frontend/views/site/error.php b/src/frontend/views/site/error.php new file mode 100644 index 0000000..b0b94db --- /dev/null +++ b/src/frontend/views/site/error.php @@ -0,0 +1 @@ + diff --git a/src/frontend/views/site/index.php b/src/frontend/views/site/index.php new file mode 100644 index 0000000..842da30 --- /dev/null +++ b/src/frontend/views/site/index.php @@ -0,0 +1,50 @@ +
              + + +
              +

              Hello, world!

              + +

              This is a template for a simple marketing or informational website. It includes a large callout called the + hero unit and three supporting pieces of content. Use it as a starting point to create something more + unique.

              + +

              Learn more »

              +
              + + +
              +
              +

              Heading

              + +

              Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris + condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis + euismod. Donec sed odio dui.

              + +

              View details »

              +
              +
              +

              Heading

              + +

              Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris + condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis + euismod. Donec sed odio dui.

              + +

              View details »

              +
              +
              +

              Heading

              + +

              Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula + porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut + fermentum massa justo sit amet risus.

              + +

              View details »

              +
              +
              + +
              + +
              +

              © Company 2012

              +
              +
              \ No newline at end of file diff --git a/src/frontend/widgets/.gitkeep b/src/frontend/widgets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/www/.htaccess b/src/frontend/www/.htaccess new file mode 100644 index 0000000..27aed38 --- /dev/null +++ b/src/frontend/www/.htaccess @@ -0,0 +1,550 @@ +# Apache configuration file +# httpd.apache.org/docs/2.2/mod/quickreference.html + +# Note .htaccess files are an overhead, this logic should be in your Apache +# config if possible: httpd.apache.org/docs/2.2/howto/htaccess.html + +# Techniques in here adapted from all over, including: +# Kroc Camen: camendesign.com/.htaccess +# perishablepress.com/press/2006/01/10/stupid-htaccess-tricks/ +# Sample .htaccess file of CMS MODx: modxcms.com + + +# ---------------------------------------------------------------------- +# Better website experience for IE users +# ---------------------------------------------------------------------- + +# Force the latest IE version, in various cases when it may fall back to IE7 mode +# github.com/rails/rails/commit/123eb25#commitcomment-118920 +# Use ChromeFrame if it's installed for a better experience for the poor IE folk + + + Header set X-UA-Compatible "IE=Edge,chrome=1" + # mod_headers can't match by content-type, but we don't want to send this header on *everything*... + + Header unset X-UA-Compatible + + + + +# ---------------------------------------------------------------------- +# Cross-domain AJAX requests +# ---------------------------------------------------------------------- + +# Serve cross-domain Ajax requests, disabled by default. +# enable-cors.org +# code.google.com/p/html5security/wiki/CrossOriginRequestSecurity + +# +# Header set Access-Control-Allow-Origin "*" +# + + +# ---------------------------------------------------------------------- +# CORS-enabled images (@crossorigin) +# ---------------------------------------------------------------------- + +# Send CORS headers if browsers request them; enabled by default for images. +# developer.mozilla.org/en/CORS_Enabled_Image +# blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html +# hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ +# wiki.mozilla.org/Security/Reviews/crossoriginAttribute + + + + # mod_headers, y u no match by Content-Type?! + + SetEnvIf Origin ":" IS_CORS + Header set Access-Control-Allow-Origin "*" env=IS_CORS + + + + + +# ---------------------------------------------------------------------- +# Webfont access +# ---------------------------------------------------------------------- + +# Allow access from all domains for webfonts. +# Alternatively you could only whitelist your +# subdomains like "subdomain.example.com". + + + + Header set Access-Control-Allow-Origin "*" + + + + +# ---------------------------------------------------------------------- +# Proper MIME type for all files +# ---------------------------------------------------------------------- + +# JavaScript +# Normalize to standard type (it's sniffed in IE anyways) +# tools.ietf.org/html/rfc4329#section-7.2 +AddType application/javascript js jsonp +AddType application/json json + +# Audio +AddType audio/ogg oga ogg +AddType audio/mp4 m4a f4a f4b + +# Video +AddType video/ogg ogv +AddType video/mp4 mp4 m4v f4v f4p +AddType video/webm webm +AddType video/x-flv flv + +# SVG +# Required for svg webfonts on iPad +# twitter.com/FontSquirrel/status/14855840545 +AddType image/svg+xml svg svgz +AddEncoding gzip svgz + +# Webfonts +AddType application/vnd.ms-fontobject eot +AddType application/x-font-ttf ttf ttc +AddType font/opentype otf +AddType application/x-font-woff woff + +# Assorted types +AddType image/x-icon ico +AddType image/webp webp +AddType text/cache-manifest appcache manifest +AddType text/x-component htc +AddType application/xml rss atom xml rdf +AddType application/x-chrome-extension crx +AddType application/x-opera-extension oex +AddType application/x-xpinstall xpi +AddType application/octet-stream safariextz +AddType application/x-web-app-manifest+json webapp +AddType text/x-vcard vcf +AddType application/x-shockwave-flash swf +AddType text/vtt vtt + + +# ---------------------------------------------------------------------- +# Allow concatenation from within specific js and css files +# ---------------------------------------------------------------------- + +# e.g. Inside of script.combined.js you could have +# +# +# and they would be included into this single file. + +# This is not in use in the boilerplate as it stands. You may +# choose to use this technique if you do not have a build process. + +# +# Options +Includes +# AddOutputFilterByType INCLUDES application/javascript application/json +# SetOutputFilter INCLUDES +# + +# +# Options +Includes +# AddOutputFilterByType INCLUDES text/css +# SetOutputFilter INCLUDES +# + + +# ---------------------------------------------------------------------- +# Gzip compression +# ---------------------------------------------------------------------- + + + + # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/ + + + SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding + RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding + + + + # Compress all output labeled with one of the following MIME-types + + AddOutputFilterByType DEFLATE application/atom+xml \ + application/javascript \ + application/json \ + application/rss+xml \ + application/vnd.ms-fontobject \ + application/x-font-ttf \ + application/xhtml+xml \ + application/xml \ + font/opentype \ + image/svg+xml \ + image/x-icon \ + text/css \ + text/html \ + text/plain \ + text/x-component \ + text/xml + + + + + +# ---------------------------------------------------------------------- +# Expires headers (for better cache control) +# ---------------------------------------------------------------------- + +# These are pretty far-future expires headers. +# They assume you control versioning with filename-based cache busting +# Additionally, consider that outdated proxies may miscache +# www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/ + +# If you don't use filenames to version, lower the CSS and JS to something like +# "access plus 1 week". + + + ExpiresActive on + +# Perhaps better to whitelist expires rules? Perhaps. + ExpiresDefault "access plus 1 month" + +# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5) + ExpiresByType text/cache-manifest "access plus 0 seconds" + +# Your document html + ExpiresByType text/html "access plus 0 seconds" + +# Data + ExpiresByType text/xml "access plus 0 seconds" + ExpiresByType application/xml "access plus 0 seconds" + ExpiresByType application/json "access plus 0 seconds" + +# Feed + ExpiresByType application/rss+xml "access plus 1 hour" + ExpiresByType application/atom+xml "access plus 1 hour" + +# Favicon (cannot be renamed) + ExpiresByType image/x-icon "access plus 1 week" + +# Media: images, video, audio + ExpiresByType image/gif "access plus 1 month" + ExpiresByType image/png "access plus 1 month" + ExpiresByType image/jpeg "access plus 1 month" + ExpiresByType video/ogg "access plus 1 month" + ExpiresByType audio/ogg "access plus 1 month" + ExpiresByType video/mp4 "access plus 1 month" + ExpiresByType video/webm "access plus 1 month" + +# HTC files (css3pie) + ExpiresByType text/x-component "access plus 1 month" + +# Webfonts + ExpiresByType application/x-font-ttf "access plus 1 month" + ExpiresByType font/opentype "access plus 1 month" + ExpiresByType application/x-font-woff "access plus 1 month" + ExpiresByType image/svg+xml "access plus 1 month" + ExpiresByType application/vnd.ms-fontobject "access plus 1 month" + +# CSS and JavaScript + ExpiresByType text/css "access plus 1 year" + ExpiresByType application/javascript "access plus 1 year" + + + + +# ---------------------------------------------------------------------- +# Prevent mobile network providers from modifying your site +# ---------------------------------------------------------------------- + +# The following header prevents modification of your code over 3G on some +# European providers. +# This is the official 'bypass' suggested by O2 in the UK. + +# +# Header set Cache-Control "no-transform" +# + + +# ---------------------------------------------------------------------- +# ETag removal +# ---------------------------------------------------------------------- + +# FileETag None is not enough for every server. + + Header unset ETag + + +# Since we're sending far-future expires, we don't need ETags for +# static content. +# developer.yahoo.com/performance/rules.html#etags +FileETag None + + +# ---------------------------------------------------------------------- +# Stop screen flicker in IE on CSS rollovers +# ---------------------------------------------------------------------- + +# The following directives stop screen flicker in IE on CSS rollovers - in +# combination with the "ExpiresByType" rules for images (see above). + +# BrowserMatch "MSIE" brokenvary=1 +# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 +# BrowserMatch "Opera" !brokenvary +# SetEnvIf brokenvary 1 force-no-vary + + +# ---------------------------------------------------------------------- +# Set Keep-Alive Header +# ---------------------------------------------------------------------- + +# Keep-Alive allows the server to send multiple requests through one +# TCP-connection. Be aware of possible disadvantages of this setting. Turn on +# if you serve a lot of static content. + +# +# Header set Connection Keep-Alive +# + + +# ---------------------------------------------------------------------- +# Cookie setting from iframes +# ---------------------------------------------------------------------- + +# Allow cookies to be set from iframes (for IE only) +# If needed, specify a path or regex in the Location directive. + +# +# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" +# + + +# ---------------------------------------------------------------------- +# Start rewrite engine +# ---------------------------------------------------------------------- + +# Turning on the rewrite engine is necessary for the following rules and +# features. FollowSymLinks must be enabled for this to work. + +# Some cloud hosting services require RewriteBase to be set: goo.gl/HOcPN +# If using the h5bp in a subdirectory, use `RewriteBase /foo` instead where +# 'foo' is your directory. + +# If your web host doesn't allow the FollowSymlinks option, you may need to +# comment it out and use `Options +SymLinksIfOwnerMatch`, but be aware of the +# performance impact: http://goo.gl/Mluzd + + + Options +FollowSymlinks +# Options +SymLinksIfOwnerMatch + RewriteEngine On +# RewriteBase / +# If you are in a sub folder of your web root you +# might have to enable something like this: +# +# RewriteBase /~antonio/app/frontend/www + +# Yii rewrite + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + + RewriteRule . index.php + + + +# ---------------------------------------------------------------------- +# Suppress or force the "www." at the beginning of URLs +# ---------------------------------------------------------------------- + +# The same content should never be available under two different URLs - +# especially not with and without "www." at the beginning, since this can cause +# SEO problems (duplicate content). That's why you should choose one of the +# alternatives and redirect the other one. + +# By default option 1 (no "www.") is activated. +# no-www.org/faq.php?q=class_b + +# If you'd prefer to use option 2, just comment out all option 1 lines +# and uncomment option 2. + +# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! + +# ---------------------------------------------------------------------- + +# Option 1: +# Rewrite "www.example.com -> example.com". + + + RewriteCond %{HTTPS} !=on + RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] + RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] + + +# ---------------------------------------------------------------------- + +# Option 2: +# Rewrite "example.com -> www.example.com". +# Be aware that the following rule might not be a good idea if you use "real" +# subdomains for certain parts of your website. + +# +# RewriteCond %{HTTPS} !=on +# RewriteCond %{HTTP_HOST} !^www\..+$ [NC] +# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] +# + + +# ---------------------------------------------------------------------- +# Built-in filename-based cache busting +# ---------------------------------------------------------------------- + +# If you're not using the build script to manage your filename version revving, +# you might want to consider enabling this, which will route requests for +# `/css/style.20110203.css` to `/css/style.css`. + +# To understand why this is important and a better idea than all.css?v1231, +# please refer to the bundled documentation about `.htaccess`. + +# +# RewriteCond %{REQUEST_FILENAME} !-f +# RewriteCond %{REQUEST_FILENAME} !-d +# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] +# + + +# ---------------------------------------------------------------------- +# Prevent SSL cert warnings +# ---------------------------------------------------------------------- + +# Rewrite secure requests properly to prevent SSL cert warnings, e.g. prevent +# https://www.example.com when your cert only allows https://secure.example.com + +# +# RewriteCond %{SERVER_PORT} !^443 +# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] +# + + +# ---------------------------------------------------------------------- +# Prevent 404 errors for non-existing redirected folders +# ---------------------------------------------------------------------- + +# without -MultiViews, Apache will give a 404 for a rewrite if a folder of the +# same name does not exist. +# webmasterworld.com/apache/3808792.htm + +Options -MultiViews + + +# ---------------------------------------------------------------------- +# Custom 404 page +# ---------------------------------------------------------------------- + +# You can add custom pages to handle 500 or 403 pretty easily, if you like. +# If you are hosting your site in subdirectory, adjust this accordingly +# e.g. ErrorDocument 404 /subdir/404.html +# ErrorDocument 404 /404.html + + +# ---------------------------------------------------------------------- +# UTF-8 encoding +# ---------------------------------------------------------------------- + +# Use UTF-8 encoding for anything served text/plain or text/html +AddDefaultCharset utf-8 + +# Force UTF-8 for a number of file formats +AddCharset utf-8 .atom .css .js .json .rss .vtt .xml + + +# ---------------------------------------------------------------------- +# A little more security +# ---------------------------------------------------------------------- + +# To avoid displaying the exact version number of Apache being used, add the +# following to httpd.conf (it will not work in .htaccess): +# ServerTokens Prod + +# "-Indexes" will have Apache block users from browsing folders without a +# default document Usually you should leave this activated, because you +# shouldn't allow everybody to surf through every folder on your server (which +# includes rather private places like CMS system folders). + + Options -Indexes + + +# Block access to "hidden" directories or files whose names begin with a +# period. This includes directories used by version control systems such as +# Subversion or Git. + + RewriteCond %{SCRIPT_FILENAME} -d [OR] + RewriteCond %{SCRIPT_FILENAME} -f + RewriteRule "(^|/)\." - [F] + + +# Block access to backup and source files. These files may be left by some +# text/html editors and pose a great security danger, when anyone can access +# them. + + Order allow,deny + Deny from all + Satisfy All + + +# If your server is not already configured as such, the following directive +# should be uncommented in order to set PHP's register_globals option to OFF. +# This closes a major security hole that is abused by most XSS (cross-site +# scripting) attacks. For more information: http://php.net/register_globals +# +# IF REGISTER_GLOBALS DIRECTIVE CAUSES 500 INTERNAL SERVER ERRORS: +# +# Your server does not allow PHP directives to be set via .htaccess. In that +# case you must make this change in your php.ini file instead. If you are +# using a commercial web host, contact the administrators for assistance in +# doing this. Not all servers allow local php.ini files, and they should +# include all PHP configurations (not just this one), or you will effectively +# reset everything to PHP defaults. Consult www.php.net for more detailed +# information about setting PHP directives. + +# php_flag register_globals Off + +# Rename session cookie to something else, than PHPSESSID +# php_value session.name sid + +# Disable magic quotes (This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.) +# php_flag magic_quotes_gpc Off + +# Do not show you are using PHP +# Note: Move this line to php.ini since it won't work in .htaccess +# php_flag expose_php Off + +# Level of log detail - log all errors +# php_value error_reporting -1 + +# Write errors to log file +# php_flag log_errors On + +# Do not display errors in browser (production - Off, development - On) +# php_flag display_errors Off + +# Do not display startup errors (production - Off, development - On) +# php_flag display_startup_errors Off + +# Format errors in plain text +# Note: Leave this setting 'On' for xdebug's var_dump() output +# php_flag html_errors Off + +# Show multiple occurrence of error +# php_flag ignore_repeated_errors Off + +# Show same errors from different sources +# php_flag ignore_repeated_source Off + +# Size limit for error messages +# php_value log_errors_max_len 1024 + +# Don't precede error with string (doesn't accept empty string, use whitespace if you need) +# php_value error_prepend_string " " + +# Don't prepend to error (doesn't accept empty string, use whitespace if you need) +# php_value error_append_string " " + +# Increase cookie security + + php_value session.cookie_httponly true + \ No newline at end of file diff --git a/src/frontend/www/apple-touch-icon-114x114-precomposed.png b/src/frontend/www/apple-touch-icon-114x114-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..de2d59f92cae78ec291461ca1d5de47763d391b7 GIT binary patch literal 1032 zcmeAS@N?(olHy`uVBq!ia0vp^MIg+<3?z3jm-+*#0|7oEuAb@nZs`RN(~N;6gyEN- z3+F;afLxc<-216Uktu06Q;aSr89OFso=Gq|7H4E1o0=0FZWo=jH`;JpgkgDvpKW;D zx=@4W5U0gK2G&90GXjhz`Wf5!1$w)=1UXs7S!-)r+QeFEhMQ~Xn3@KeshgM>`I@NP z8)~ZP>Z<7JDQT!GsbfcqsNymzDsrkSdow=8F)%PQd%8G=WZZi@)BpS;1A%sR+c&*$ z4rRxAiiikxNM-MQ%e(*o_NY_xYdcEPPHnom#8!Cz2MgoBy-r(yG4_A)fT0urIah|c zuUhkOuhAxsY;`r}nO(uPeWyexdUdQ>$9N;aYLmbs!)gXI5s5h0nCO>w@nnXFXq9+=A&U?x1Ul;f~EnA@YTF=q#8R6z( zD`#x%%elB?)o#;r3+to%Jp*)Cy?&Oq=h2(mwjF!c=^(^1Z;VTkQ^F*Baf8yB(H2UdM6w4Aaf*n7iNo zPICtAP5U*^E9RQrf=XGZ$LD$L-!f0So}Te%WBp!VjlJg3{JyXvXji1P(VQC(;_NIr zt2e7&(@FTZXvWhq3W!gXN{7{s|D6G&dN?~ zQ^@(Boy%*oFoPT!igj|>RqhB{O7*jqws{Tulo4VTdKX25diY4w6@I{R}PqLv#F{+q{jceJoAA1B_ig4IEwcZR~U{taMDxH4Kf^_4Jjr zG!->9)HGCev{aQfR29`#l~9o~Di>My>B*mV3=E9bo-U3d9>?EKJJ{D`Akg;w+T=Bj zS9(=C8bnx9Y~JPG`@eRZYtok6WfR^^v=p4AU-RelbcXL+nWcA5v?(!`<3v{M z)9bAbYp(6(EKE3I=pCPCK6!$d=Gop$XDW*AihUGqs#TWW*%m6`v(o;>lBu6<4L>%E zzTEIdhCSUW`PoC2ONC6?`P+`3W1V)zwXJ*ifv|voy~~!K{&L{5z`gWL_hvOIMWv%= z4`rt=QM>GXzWjylGTWnJCUHeua-#oE3f#S9d#mfSz30*bAHSXJx9c#|C(YUWU#((& zqBC2e_I&D@^?tDhr_-(+ee}9;?u0mQf4@z?yI!p{?KfIZFjlG{O zyMNt1d)LlDH}j;EcQ@aEUMZaW=-O8QnMY>deQ#L&DoQ2j@eA`;{s~9&mYO{|TDU#& pw)vHfi|;$f=GO;F|2+Rh|Lbff^@O$?_P`{?;OXk;vd$@?2>^oK4mtn; literal 0 HcmV?d00001 diff --git a/src/frontend/www/apple-touch-icon-72x72-precomposed.png b/src/frontend/www/apple-touch-icon-72x72-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..b20e78ef3920a3f46e552fe179c5d59dabd675c6 GIT binary patch literal 747 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAk#fdHQn*N17wXy|^Lv0Hip4CT9| z=7yza-Apk~PENU;WaONb?HHeaBF@l0Hf3*=fo){M)^Pom;U{jZOSb)V+<>-3-<3_0=2=)U0&Xl(e;tv{g-Y)bzDg zl{A1zO977@wzny-%ui1ddb?@mU zITMj6r-e%t6a_iYR)zihzkilUMrQZt1si6t{%lw*b9|q~kI0t?*lsyUzo>6eS;xGJ zS*Od?fywLWqa;fWrp7rNOEgz7a(p-|o(}GK~_(^P;m#IBg6Po2TkYR=e#L*=_qH=J_q2Uo|P) z!i!(9s;=7c{EhbS&({~W3U8h9w(8u;o9?+um%Z569$K!b8vA*}v99lPB7T;Z`ECtq zn(#2{j(bdUqTKgGyg+`v0xHV0x`<;{g^T^Bkol>QuU8^e%ok|-*F25^mV)}G- zi}ZZ%}Z`jN>C*MDPKi=H@v=D=sacAx84d*Ys zWpmqHE%54nyU^he#gChq)i$T_9Lio4=XAV@c}t{$*c>lb=W@@3bL(-Y=(-m@Db7Ssln68nS`TlMqoB5}otKT`zx%0i)Pv4^LrGC&| wo3_Lgm3HZCH?BQgY*hVQ^sa++M(hRo#B*|C9>pOFz|_m&>FVdQ&MBb@0NJQ0PXGV_ literal 0 HcmV?d00001 diff --git a/src/frontend/www/apple-touch-icon-precomposed.png b/src/frontend/www/apple-touch-icon-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..6d2fc3969d2a377bc1b0e345e20ef5c15bd21a2f GIT binary patch literal 640 zcmeAS@N?(olHy`uVBq!ia0vp^mLSZ*3?z3SE8Y&I4g~mwxIRoXMnezMjNH--+|u*G zWWl{uBiGct8!5&vDY;%L*%y6@I{R}PqLv#F{+q{jceJoAA1B_ig4IEwcZR~U{taMDxH4Kf^_4Jjr zG!->9)HGCev{aQfR29`#l~9o~Di>My>B*mV3=E9bo-U3d9>?EKJJ{D`Akg;w+T=Bj zS9(=C8bnx9Y~JPG`@eRZYtok6WfR^^v=p4AU-RelbcXL+nWcA5v?(!`<3v{M z)9bAbYp(6(EKE3I=pCPCK6!$d=Gop$XDW*AihUGqs#TWW*%m6`v(o;>lBu6<4L>%E zzTEIdhCSUW`PoC2ONC6?`P+`3W1V)zwXJ*ifv|voy~~!K{&L{5z`gWL_hvOIMWv%= z4`rt=QM>GXzWjylGTWnJCUHeua-#oE3f#S9d#mfSz30*bAHSXJx9c#|C(YUWU#((& zqBC2e_I&D@^?tDhr_-(+ee}9;?u0mQf4@z?yI!p{?KfIZFjlG{O zyMNt1d)LlDH}j;EcQ@aEUMZaW=-O8QnMY>deQ#L&DoQ2j@eA`;{s~9&mYO{|TDU#& pw)vHfi|;$f=GO;F|2+Rh|Lbff^@O$?_P`{?;OXk;vd$@?2>^oK4mtn; literal 0 HcmV?d00001 diff --git a/src/frontend/www/apple-touch-icon.png b/src/frontend/www/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6d2fc3969d2a377bc1b0e345e20ef5c15bd21a2f GIT binary patch literal 640 zcmeAS@N?(olHy`uVBq!ia0vp^mLSZ*3?z3SE8Y&I4g~mwxIRoXMnezMjNH--+|u*G zWWl{uBiGct8!5&vDY;%L*%y6@I{R}PqLv#F{+q{jceJoAA1B_ig4IEwcZR~U{taMDxH4Kf^_4Jjr zG!->9)HGCev{aQfR29`#l~9o~Di>My>B*mV3=E9bo-U3d9>?EKJJ{D`Akg;w+T=Bj zS9(=C8bnx9Y~JPG`@eRZYtok6WfR^^v=p4AU-RelbcXL+nWcA5v?(!`<3v{M z)9bAbYp(6(EKE3I=pCPCK6!$d=Gop$XDW*AihUGqs#TWW*%m6`v(o;>lBu6<4L>%E zzTEIdhCSUW`PoC2ONC6?`P+`3W1V)zwXJ*ifv|voy~~!K{&L{5z`gWL_hvOIMWv%= z4`rt=QM>GXzWjylGTWnJCUHeua-#oE3f#S9d#mfSz30*bAHSXJx9c#|C(YUWU#((& zqBC2e_I&D@^?tDhr_-(+ee}9;?u0mQf4@z?yI!p{?KfIZFjlG{O zyMNt1d)LlDH}j;EcQ@aEUMZaW=-O8QnMY>deQ#L&DoQ2j@eA`;{s~9&mYO{|TDU#& pw)vHfi|;$f=GO;F|2+Rh|Lbff^@O$?_P`{?;OXk;vd$@?2>^oK4mtn; literal 0 HcmV?d00001 diff --git a/src/frontend/www/css/bootstrap-responsive.css b/src/frontend/www/css/bootstrap-responsive.css new file mode 100644 index 0000000..5215a5d --- /dev/null +++ b/src/frontend/www/css/bootstrap-responsive.css @@ -0,0 +1,1109 @@ +/*! + * Bootstrap Responsive v2.3.0 + * + * 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/src/frontend/www/css/bootstrap-responsive.min.css b/src/frontend/www/css/bootstrap-responsive.min.css new file mode 100644 index 0000000..0597860 --- /dev/null +++ b/src/frontend/www/css/bootstrap-responsive.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap Responsive v2.3.0 + * + * 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:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-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:#999}.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:#111}.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:0;-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:#111;border-bottom-color:#111}.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/src/frontend/www/css/bootstrap.css b/src/frontend/www/css/bootstrap.css new file mode 100644 index 0000000..b255056 --- /dev/null +++ b/src/frontend/www/css/bootstrap.css @@ -0,0 +1,6158 @@ +/*! + * Bootstrap v2.3.0 + * + * 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/src/frontend/www/css/bootstrap.min.css b/src/frontend/www/css/bootstrap.min.css new file mode 100644 index 0000000..fd5ed73 --- /dev/null +++ b/src/frontend/www/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.3.0 + * + * 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:.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:#333;background-color:#fff}a{color:#08c;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:#999}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:#999}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 #eee}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 #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;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:#333;-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:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}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:#555;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:#fff;border:1px solid #ccc;-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 .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .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;-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;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}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:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-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:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.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:#eee}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 #fff;background-color:#eee;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;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.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 #ddd}.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 #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;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 #ddd}.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}.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 #000;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:#fff;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 #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#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:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#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:#999}.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 #000;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:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.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 .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.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:#333;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,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*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:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .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:.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:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #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:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;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:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;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:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;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:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;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:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;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:#fff;background-color:#222;*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:#08c;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:#333;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:#04c}.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:#222}.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:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*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:#eee}.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:#999;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:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.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 #fff}.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:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;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:#fff;background-color:#08c}.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:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.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:#555;border-bottom-color:#555}.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:#fff;background-color:#999;border-color:#999}.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:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.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:#eee #ddd #eee #eee}.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:#fff}.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:#eee #eee #eee #ddd}.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:#fff}.nav>.disabled>a{color:#999}.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,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#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:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;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:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;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:#fff;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:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \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 #fff;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 #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.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:#555;border-bottom-color:#555}.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,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);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:#999;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:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.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:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.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:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-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:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;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:#fff;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 #000;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:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \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 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.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:#fff;border:1px solid #ddd;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:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;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:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;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:0;-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 .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .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 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.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:.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:#fff;text-align:center;text-decoration:none;background-color:#000;-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:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;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:#fff;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:#fff;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:#fff;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:#fff;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:#fff;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 .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-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:#555}.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:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.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:#fff;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:#333}.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:#fff;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 .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .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:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.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:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.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:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.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:#eee;-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/src/frontend/www/css/fonts/Chunkfive-webfont.eot b/src/frontend/www/css/fonts/Chunkfive-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..a540c2590b54e1c2b40cd0bdc8d9efe412cb8a59 GIT binary patch literal 18610 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 + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Generated in 2009 by FontLab Studio Copyright info pending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/frontend/www/css/fonts/Chunkfive-webfont.ttf b/src/frontend/www/css/fonts/Chunkfive-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2dc041a3ee4286a1b508a4fd5a3c5d4e193c6769 GIT binary patch literal 18412 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 literal 0 HcmV?d00001 diff --git a/src/frontend/www/css/fonts/Chunkfive-webfont.woff b/src/frontend/www/css/fonts/Chunkfive-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..b2048008ae66fa9b1afb30fcd69c2a1bddef44a9 GIT binary patch literal 12136 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 a^tzgW8b}iH8gP0sU=7s&I$AXt^#2FO|Le5? literal 0 HcmV?d00001 diff --git a/src/frontend/www/css/fonts/League_Gothic-webfont.eot b/src/frontend/www/css/fonts/League_Gothic-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..e354b5616665ebb6c333b9564ad0e3c937365187 GIT binary patch literal 25486 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 literal 0 HcmV?d00001 diff --git a/src/frontend/www/css/fonts/League_Gothic-webfont.svg b/src/frontend/www/css/fonts/League_Gothic-webfont.svg new file mode 100644 index 0000000..d41ff8b --- /dev/null +++ b/src/frontend/www/css/fonts/League_Gothic-webfont.svg @@ -0,0 +1,148 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Generated in 2009 by FontLab Studio Copyright info pending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/frontend/www/css/fonts/League_Gothic-webfont.ttf b/src/frontend/www/css/fonts/League_Gothic-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7ea9d0dd395024eefff514984bd93aa5bfabf8fb GIT binary patch literal 25272 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 literal 0 HcmV?d00001 diff --git a/src/frontend/www/css/main.css b/src/frontend/www/css/main.css new file mode 100644 index 0000000..b25e769 --- /dev/null +++ b/src/frontend/www/css/main.css @@ -0,0 +1,22 @@ + + +/* ========================================================================== + Author's custom styles + ========================================================================== */ + + + + + + + + + + + + + + + + + diff --git a/src/frontend/www/css/style.css b/src/frontend/www/css/style.css new file mode 100644 index 0000000..a3d2cb2 --- /dev/null +++ b/src/frontend/www/css/style.css @@ -0,0 +1,767 @@ +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } +audio[controls], canvas, video { display: inline-block; *display: inline; *zoom: 1; } +html { font-size: 100%; overflow-y: scroll; -webkit-overflow-scrolling: touch; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } +body { margin: 0; font-size: 13px; line-height: 1.231; } +body, button, input, select, textarea { font-family: sans-serif; color: #222; } +::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; } +::selection { background: #fe57a1; color: #fff; text-shadow: none; } +a { color: #00e; } +a:visited { color: #551a8b; } +a:focus { outline: thin dotted; } +a:hover, a:active { outline: 0; } +abbr[title] { border-bottom: 1px dotted; } +b, strong { font-weight: bold; } +blockquote { margin: 1em 40px; } +dfn { font-style: italic; } +hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } +ins { background: #ff9; color: #000; text-decoration: none; } +mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } +pre, code, kbd, samp { font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 1em; } +pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } +q { quotes: none; } +q:before, q:after { content: ""; content: none; } +small { font-size: 85%; } +sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } +sup { top: -0.5em; } +sub { bottom: -0.25em; } +ul, ol { margin: 1em 0; padding: 0 0 0 40px; } +dd { margin: 0 0 0 40px; } +nav ul, nav ol { list-style: none; margin: 0; padding: 0; } +img { border: 0; -ms-interpolation-mode: bicubic; } +svg:not(:root) { + overflow: hidden; +} +figure { margin: 0; } +form { margin: 0; } +fieldset { border: 0; margin: 0; padding: 0; } +legend { border: 0; *margin-left: -7px; padding: 0; } +label { cursor: pointer; } +button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } +button, input { line-height: normal; *overflow: visible; } +button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; } +input[type="checkbox"], input[type="radio"] { box-sizing: border-box; } +input[type="search"] { -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; } +button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } +textarea { overflow: auto; vertical-align: top; } +input:valid, textarea:valid { } +input:invalid, textarea:invalid { background-color: #f0dddd; } +table { border-collapse: collapse; border-spacing: 0; } + + + + + + +@font-face { + font-family: 'ChunkFiveRegular'; + src: url('fonts/Chunkfive-webfont.eot'); + src: url('fonts/Chunkfive-webfont.eot?#iefix') format('embedded-opentype'), + url('fonts/Chunkfive-webfont.woff') format('woff'), + url('fonts/Chunkfive-webfont.ttf') format('truetype'), + url('fonts/Chunkfive-webfont.svg#ChunkFiveRegular') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'LeagueGothicRegular'; + src: url('fonts/League_Gothic-webfont.eot'); + src: url('fonts/League_Gothic-webfont.eot?#iefix') format('embedded-opentype'), + url('fonts/League_Gothic-webfont.woff') format('woff'), + url('fonts/League_Gothic-webfont.ttf') format('truetype'), + url('fonts/League_Gothic-webfont.svg#LeagueGothicRegular') format('svg'); + font-weight: normal; + font-style: normal; +} + + + +/* =================================================== + Initializr styles + http://verekia.com/initializr/responsive-template + Author: Jonathan Verrecchia + =================================================== */ + +body{ font:16px/26px Helvetica, Helvetica Neue, Arial; } + +.wrapper{ + width:90%; + margin:0 5%; +} + +/* =================== + ALL: Orange Theme + =================== */ + +#header-container{ border-bottom: 13px solid #e44d26; } +#footer-container{ border-top: 20px solid #e44d26; } +#main aside { border-top: 20px solid #e44d26; } + +#header-container, +#footer-container, +#main aside{ + background:#f16529; +} + +#title{ + color:white; + font-family:'ChunkFiveRegular'; + font-weight:normal; + font-size:4em; + margin-bottom:20px; +} + +#header-container h2{ + color:white; + font-size:16px; +} + +#header-container header{ + text-align:center; +} + +::-moz-selection { background: #f16529; color: #fff; text-shadow: none; } +::selection { background: #f16529; color: #fff; text-shadow: none; } + + + +/* WEBSITE */ + +#html5-logo-container{ + display:none; +} + +#follow-container{ + display:none; +} + + + #badges{ + margin:0 auto; + width:265px; + margin-top:10px; + line-height:18px; + font-size:14px; + color:white; + font-weight:bold; + font-style:italic; + + } + + #badges li{ + float:left; + background:#eee; + color:#444; + text-align:center; + width:85px; + height:85px; +/* border:10px solid #E44D26; */ + -webkit-border-radius:999px; + -moz-border-radius:999px; + border-radius:999px; + margin-left:5px; + text-shadow:0 2px 1px white; + box-shadow:1px 1px 1px rgba(0, 0, 0, 0.4); + } + + #badges li:first-child{ + margin-left:0; + } + + .badge-label{ + margin-top:26px; + } + + #badges ul{ + float:right; + margin:0; + list-style-type:none; + padding:0; + } + + +.separator{ + font-family:LeagueGothicRegular; + text-align:center; + font-weight:normal; + font-size:3em; + color:#F16529; + margin:50px 0; +} + +.separator:before, +.separator:after{ + width:20%; + height:4px; + display:block; + background:#eee; + content:""; + margin-top:14px; + display:none; +} + + +.separator:before{ + float:left; +} + +.separator:after{ + float:right; +} + +#fine-tuning-separator{ + margin:30px 0 20px; +} + +.blank-background button, +.blank-background a{ + background:#bbb; +} + +.blank-background button:hover, +.blank-background a:hover{ + background:#c4c4c4; +} + +.blank-background button:active{ + background:#888; +} + + + +.initializr-background button, +.initializr-background a, +#download-section a{ + background:#F16529; +} + +.initializr-background button:hover, +.initializr-background a:hover, +#download-section a:hover{ + background:#F67539; +} + +.initializr-background button:active{ + background:#d14509; +} + +.bootstrap-background button, +.bootstrap-background a{ + background:#6090ff; +} + +.bootstrap-background button:hover, +.bootstrap-background a:hover{ + background:#78a0ff; +} + +.bootstrap-background button:active{ + background:#4070df; +} + +#preconfig-section{ + padding-bottom:10px; +} + +.preconfig-container{ + display:block; + width:100%; +} + +.preconfig-block{ + border:none; + display:block; + width:100%; +} + +#preconfig-section h3, +#download-section a +{ + font-weight:normal; + font-family:ChunkFiveRegular; + font-size:2em; + color:white; + margin:0; + text-align:center; + padding:25px 0; + text-shadow:0 -2px 2px rgba(0, 0, 0, 0.1); + color:white; +} + +.preconfig-links-container{ + width:100px; + margin:6px auto; +} + +#preconfig-section a{ + padding:4px; + color:white; + font-weight:bold; + text-decoration:none; + margin:0px; + -webkit-border-radius:0 3px 3px 0; + -moz-border-radius:0 3px 3px 0; + border-radius:0 3px 3px 0; +} + +#preconfig-section a.first{ + -webkit-border-radius:3px 0 0 3px; + -moz-border-radius:3px 0 0 3px; + border-radius:3px 0 0 3px; +} + + +#main{ + padding:30px 0; +} + +#customize-section label{ + background:white; + -webkit-border-radius:4px; + -moz-border-radius:4px; + border-radius:4px; + + border:1px solid #ccc; + border-top:0; + border-left:0; + + padding:4px 8px; + display:block; + margin:0 5px 5px 0; +} + +#customize-section label:hover{ + background:#f5f5f5; +} + +#customize-section input{ + margin-right:6px; +} + +.customize-section h3{ + text-align:center; + font-weight:normal; + font-family:LeagueGothicRegular; + font-size:2em; +} + +.second-h5bp-label, +.third-h5bp-label{ + display:none; + visibility:hidden; +} + +.customize-section a{ + color:#E44D26; + text-decoration:none; +} + +textarea{ + display:block; + width:700px; +} + +#download-section{ + margin-top:50px; +} + +#download-section a{ + background:#F16529; + display:block; + text-decoration:none; + margin-bottom:20px; +} + + +#about-container{ + background:#eee; + padding:30px 0; +} + +#about-container h3{ + font-weight:normal; + font-family:LeagueGothicRegular; + font-size:2em; +} + +#about-container a{ + color:#E44D26; +/* font-weight:bold; */ + text-decoration:none; +} + +#github-container img{ + display:none; +} + + +#email:before{ + content:"initializr@gmail.com"; +} + +/* =============== + ALL: IE Fixes + =============== */ + +.ie7 #title{ padding-top:20px; } + + + +/* ============================================================================= + Non-semantic helper classes + Please define your styles before this section. + ========================================================================== */ + +/* For image replacement */ +.ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; text-align: left; direction: ltr; } +.ir br { display: none; } + +/* Hide for both screenreaders and browsers: + css-discuss.incutio.com/wiki/Screenreader_Visibility */ +.hidden { display: none; visibility: hidden; } + +/* Hide only visually, but have it available for screenreaders: by Jon Neal. + www.webaim.org/techniques/css/invisiblecontent/ & j.mp/visuallyhidden */ +.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } + +/* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: drupal.org/node/897638 */ +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } + +/* Hide visually and from screenreaders, but maintain layout */ +.invisible { visibility: hidden; } + +/* Contain floats: nicolasgallagher.com/micro-clearfix-hack/ */ +.clearfix:before, .clearfix:after { content: ""; display: table; } +.clearfix:after { clear: both; } +.clearfix { zoom: 1; } + + +/* ==|== media queries ====================================================== */ + +@media only screen and (min-width: 540px) { + +/* ==================== + INTERMEDIATE: Menu + ==================== */ + + #header-container{ + -webkit-box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); + -moz-box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); + box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); + } + + #header-container header{ + text-align:left; + height:133px; + } + + + .ie7 #header-container header, + .ie8 #header-container header{ + height:auto; + } + + #title, + #header-container h2, + #follow-container p{ + text-shadow:0 -2px 2px rgba(0, 0, 0, 0.1); + } + + #title-container{ + float:left; + width:63%; + } + + #html5-logo-container{ + float:left; + width:0; + } + + #follow-iframes-container{ + width:260px; + float:right; + } + + #follow-iframes-container iframe{ + float:right; + width:146px!important; + margin-bottom:6px; + } + + .ie9 #follow-iframes-container iframe, + .ie8 #follow-iframes-container iframe, + .ie7 #follow-iframes-container iframe{ + width:135px!important; + } + + + #follow-container{ + float:right; + width:37%; + display:block; + } + + #follow-container p{ + text-align:right; + color:white; + font-weight:bold; + margin:12px 0; + } + + + + #follow-container a{ + color:white; + } + + #intro p{ +/* float:left; */ + margin-right:285px; + } + + #badges{ + float:right; + } + + .separator:before, + .separator:after{ + width:20%; + display:block; + } + + .preconfig-container{ + float:left; + width:48%; + margin:0 1%; + } + + .preconfig-block{ + } + + .preconfig-container:last-child{ + margin:auto; + float:none; + clear:both; + } + + #hidden-section{ + display:none; + } + + .customize-section{ + float:left; + width:50%; + } + + .customize-section:nth-child(2n + 1){ + clear:both; + } + + .second-h5bp-label{ + display:block; + } + + #download-section a{ + float:left; + width:48%; + } + + #download-section a:first-child{ + margin-right:4%; + } + + #about-container{ + -webkit-box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); + + } + + #about-container article{ + width:100%; + } + + #github-container{ + margin:auto; + width:480px; + } + + #github-container img{ + float:left; + display:block; + } + + #github-repositories{ + float:right; + margin-top:20px; + } + + #github-repositories h3{ + text-align:center; + } + +} + +@media only screen and (min-width: 860px) { + + #title-container{ + float:left; + width:40%; + } + + #html5-logo-container{ + display:block; + float:left; + width:20%; + } + + #html5-logo-container img{ + display:block; + margin:auto; + } + + #follow-iframes-container{ + width:260px; + float:right; + } + + #follow-container{ + float:right; + width:40%; + } + + #follow-container p:before{ + content:"Initialized by "; + } + + #follow-iframes-container iframe{ +/* float:right; */ + width:auto!important; + margin-bottom:6px; + } + + .ie9 #follow-iframes-container iframe, + .ie8 #follow-iframes-container iframe, + .ie7 #follow-iframes-container iframe{ + width:auto!important; + } + + #intro p{ +/* width:56%; */ + } + + #intro #badges{ +/* width:44%; */ + } + + .separator:before, + .separator:after{ + width:31%; + } + + .preconfig-container{ + width:32%; + margin-right:2%; + margin-left:0; + } + + .preconfig-block{ + } + + .ie8 .preconfig-container, + .ie7 .preconfig-container{ + width:31.33%; + } + + .preconfig-container:last-child{ + margin:0; + float:left; + clear:none; + } + + + .first-h5bp-label{ + visibility:hidden; + } + + .second-h5bp-label{ + visibility:visible; + } + + .third-h5bp-label{ + display:block; + } + + + + .customize-section{ + width:33.3%; + } + + .customize-section:nth-child(2n + 1){ + clear:none; + } + + .customize-section:nth-child(3n + 1){ + clear:both; + } + + + #about-container article{ + width:530px; + } + + #github-container{ + float:right; + } + + #github-container img{ + float:none; + margin:0; + } + + #github-repositories{ + float:none; + margin:0; + } + + #github-container{ + width:auto; + } + + +} + + +@media only screen and (min-width: 1140px) { + +/* =============== + Maximal Width + =============== */ + + .wrapper{ + width:1026px; /* 1140px - 10% for margins */ + margin:0 auto; + } +} + + +/* ============================================================================= + Print styles. + Inlined to avoid required HTTP connection: www.phpied.com/delay-loading-your-print-css/ + ========================================================================== */ + +@media print { + * { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: sanbeiji.com/archives/953 */ + a, a:visited { color: #444 !important; 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: ""; } /* Don't show links for images, or javascript/internal links */ + pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } + thead { display: table-header-group; } /* css-discuss.incutio.com/wiki/Printing_Tables */ + 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; } +} diff --git a/src/frontend/www/favicon.ico b/src/frontend/www/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4ec0d298859a6e33a6cc40f7a502354b8cad5f76 GIT binary patch literal 1150 zcmZvc&rcIU6vv0?T~3}Vg?4v#yIp9zU1&k*FC;0yN&pE-r71xP79vXcVT>0+io~c1 z@uXK{B+(d6OeFpaN@9YEe?#HwsR-_La3ytienMto~)nRwQ- ztEU+|%NSFI377ELelaj6V$~l2tkU-O_ua*{^@FsA{g}@8q9dxKtviRl!Uob8+Ta!EAg$QvH?ga$D;u=7jC-I3O|)O%LUjBohDWow zICCGdrSIq+zm4V)7dd%ttzd{992)p}!V915J%{L}2T0!ff%9UY*uq!DZ@fotY!u;; zX657PiH$^CemQGdZh)@35gRKaxwM1C!WSeLx6xjBh3x1cW+(a)Yd0au_8EwEcrMo? z6gJQ~@d&A#Hk+9Lgv9)3Bo@CRI{6%#ksRiyhLGurTeTsU&cH?9ej|$5l_!YLeL(Em z8!>K)-xsXdBQ^KV${{lK5~)lcopIBu6|wgHNl^7h_yW!FH3p#g6d1kJ)*Ym0pP{F_ z6SAg53mD*f@Z|i&p43m&UQtACgmJkJTBrpbb03kpyo^>;fh5%*$L-vy=EPDDIQ`?? zBaNIlpe_Fx10z}ZRJ-Ptai@QXr(T?%DZH+X6CdcvAYh0yD}QTF8q!wwuhYl$ZW!U< z0rjZWr<9K>?&f$+vH!h44o_ogZ{NMVvQ|u{(z`B~x9oCBWtx+ZVwGB&AG#SUpJ8nK U6k~U4Y^(l{aMn(ow8Rkm2iEifo&W#< literal 0 HcmV?d00001 diff --git a/src/frontend/www/humans.txt b/src/frontend/www/humans.txt new file mode 100644 index 0000000..59cb7a4 --- /dev/null +++ b/src/frontend/www/humans.txt @@ -0,0 +1,20 @@ +# humanstxt.org/ +# The humans responsible & technology colophon + +/* TEAM */ + + Senior Developer: Antonio Ramirez + Contact: amigo.cobos [at] gmail.com + Twitter: @tonydspaniard + From: Majorca, Catalonia, Spain + +/* THANKS */ + + (First) Phundamente man: Tobias Munk + From: Stuttgart, Schwabenland, Germany + +/* SITE */ + Standards: HTML5, CSS3 + Components: JQuery, Modernizr, Yii Framework + Doctype: HTML5 + IDE: PhpStorm 6.0 diff --git a/src/frontend/www/img/github-logo.png b/src/frontend/www/img/github-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..29a95df0b223c9ed4d024495d423c7cc4f69e34c GIT binary patch literal 22194 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 MOsz~BFzyNe1Kmqyp#T5? literal 0 HcmV?d00001 diff --git a/src/frontend/www/img/html5-logo-165-cut.png b/src/frontend/www/img/html5-logo-165-cut.png new file mode 100644 index 0000000000000000000000000000000000000000..205fa69a885e51ce30dc27e9fb7cb375adc316ba GIT binary patch literal 6472 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 i$-7Z&%uciD{{sNS-!75 + * @link http://www.ramirezcobos.com/ + * @link http://www.2amigos.us/ + * @copyright 2013 2amigOS! Consultation Group LLC + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +require('./../../common/lib/vendor/autoload.php'); + +Yiinitializr\Helpers\Initializer::create('./../', 'frontend', array( + __DIR__ .'/../../common/config/main.php', + __DIR__ .'/../../common/config/env.php', + __DIR__ .'/../../common/config/local.php', + 'main', + 'env', + 'local' +))->run(); \ No newline at end of file diff --git a/src/frontend/www/js/libs/bootstrap.js b/src/frontend/www/js/libs/bootstrap.js new file mode 100644 index 0000000..a81171b --- /dev/null +++ b/src/frontend/www/js/libs/bootstrap.js @@ -0,0 +1,2268 @@ +/* =================================================== + * bootstrap-transition.js v2.3.0 + * 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.0 + * 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.0 + * 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.0 + * 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() + } + 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.0 + * 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.0 + * 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('.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.0 + * 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.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 = $('